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 (将#修改为@)