微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Magick ++ / NAPI模块内存泄漏

如何解决Magick ++ / NAPI模块内存泄漏

我正在使用node-addon-api编写一个本机模块,该模块利用了Magick ++库。该模块将图像的文件路径和一些参数一起返回到缓冲区。我似乎遇到了一个非常糟糕的内存泄漏问题,Massif报告该问题与所创建的缓冲区或Magick ++映像有关。这是我的C ++代码

#include <napi.h>
#include <list>
#include <Magick++.h>

using namespace std;
using namespace Magick;

class Flipworker : public Napi::AsyncWorker {
 public:
  Flipworker(Napi::Function& callback,string in_path,bool flop,string type,int delay)
      : Napi::AsyncWorker(callback),in_path(in_path),flop(flop),type(type),delay(delay) {}
  ~Flipworker() {}

  void Execute() {
    list<Image> frames;
    list<Image> coalesced;
    list<Image> mid;
    list<Image> result;
    readImages(&frames,in_path);
    coalesceImages(&coalesced,frames.begin(),frames.end());

    for (Image &image : coalesced) {
      flop ? image.flop() : image.flip();
      image.magick(type);
      mid.push_back(image);
    }

    optimizeImageLayers(&result,mid.begin(),mid.end());
    if (delay != 0) for_each(result.begin(),result.end(),animationDelayImage(delay));
    writeImages(result.begin(),&blob);
  }

  void OnOK() {
    Callback().Call({Env().Undefined(),Napi::Buffer<char>::copy(Env(),(char *)blob.data(),blob.length())});
  }

 private:
  string in_path,type;
  bool flop;
  int delay;
  Blob blob;
};

Napi::Value Flip(const Napi::CallbackInfo &info)
{
  Napi::Env env = info.Env();

  Napi::Object obj = info[0].As<Napi::Object>();
  Napi::Function cb = info[1].As<Napi::Function>();
  string path = obj.Get("path").As<Napi::String>().Utf8Value();
  bool flop = obj.Has("flop") ? obj.Get("flop").As<Napi::Boolean>().Value() : false;
  string type = obj.Get("type").As<Napi::String>().Utf8Value();
  int delay = obj.Get("delay").As<Napi::Number>().Int32Value();

  Flipworker* flipworker = new Flipworker(cb,path,flop,type,delay);
  flipworker->Queue();
  return env.Undefined();
}

Napi::Object Init(Napi::Env env,Napi::Object exports) {
  exports.Set(Napi::String::New(env,"flip"),Napi::Function::New(env,Flip));
  return exports;
}

NODE_API_MODULE(addon,Init);

还有一个示例JS脚本:

const image = require("./build/Release/image.node");

setInterval(() => {
  image.flip({ path: "/home/esm/animated.gif",type: "gif",delay: 0 },(error,buffer) => {
    console.log(buffer);
    console.log(process.memoryUsage().RSS);
  });
},10000);

这是脚本的示例输出

<Buffer 47 49 46 38 39 61 80 02 66 01 f7 00 00 38 44 3a 62 58 26 70 64 27 12 1c 4d 19 26 50 26 30 57 10 38 79 2c 37 67 35 51 57 14 47 79 35 4a 71 55 4f 4f 68 ... 868294 more bytes>
69496832
<Buffer 47 49 46 38 39 61 80 02 66 01 f7 00 00 38 44 3a 62 58 26 70 64 27 12 1c 4d 19 26 50 26 30 57 10 38 79 2c 37 67 35 51 57 14 47 79 35 4a 71 55 4f 4f 68 ... 868294 more bytes>
110673920
<Buffer 47 49 46 38 39 61 80 02 66 01 f7 00 00 38 44 3a 62 58 26 70 64 27 12 1c 4d 19 26 50 26 30 57 10 38 79 2c 37 67 35 51 57 14 47 79 35 4a 71 55 4f 4f 68 ... 868294 more bytes>
152092672
<Buffer 47 49 46 38 39 61 80 02 66 01 f7 00 00 38 44 3a 62 58 26 70 64 27 12 1c 4d 19 26 50 26 30 57 10 38 79 2c 37 67 35 51 57 14 47 79 35 4a 71 55 4f 4f 68 ... 868294 more bytes>
192970752
<Buffer 47 49 46 38 39 61 80 02 66 01 f7 00 00 38 44 3a 62 58 26 70 64 27 12 1c 4d 19 26 50 26 30 57 10 38 79 2c 37 67 35 51 57 14 47 79 35 4a 71 55 4f 4f 68 ... 868294 more bytes>
204517376

如您所见,每次运行该函数时,驻留集的大小都会显着增加。我使用的任何格式的每张图像都会发生这种情况。我如何防止代码泄漏?预先感谢。

编辑: 我做了一些进一步的挖掘,结果表明,由于缓冲区不是通过JS创建的,因此它不符合以相同方式进行垃圾收集的条件。我现在想知道是否有可能创建一个缓冲区,以获取V8收集的垃圾并仍然提供相同的数据。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。