本机 node.js 正在释放的插件错误指针未分配

Native node.js addon error pointer being freed was not allocated

我正在编写一个如下所示的函数:

Nan::MaybeLocal<v8::Object> getIconForFile(const char * str) {
  NSImage * icon = [[NSWorkspace sharedWorkspace] iconForFile:[NSString stringWithUTF8String:str]];
  NSData * tiffData = [icon TIFFRepresentation];
  unsigned int length = [tiffData length];

  //TODO this is causing `malloc: *** error for object 0x10a202000: pointer being freed was not allocated`
  char * iconBuff = (char *)[tiffData bytes];

  Nan::MaybeLocal<v8::Object> ret = Nan::NewBuffer(iconBuff, length);

  return ret;
}

它按预期工作,除了当它通过 node.js 获得 运行 时,它抛出 malloc: *** error for object 0x10a202000: pointer being freed was not allocated。我已经使用 malloc 等尝试了不同的方法,但没有任何效果。我知道 Nan::NewBuffer 正试图以某种方式释放缓冲区数据,这就是问题所在。也许 iconBuff 变量被分配到堆栈,当它超出范围并且 Nan::NewBuffer 试图释放它时,它释放了一个空指针?我不确定,我有点迷路:(


这是 "fixed" 它的代码,但@uliwitness 在他的回答中指出它仍然存在内存管理问题:

Nan::MaybeLocal<v8::Object> getIconForFile(const char * str) {
  NSImage * icon = [[NSWorkspace sharedWorkspace] iconForFile:[NSString stringWithUTF8String:str]];
  NSData * tiffData = [icon TIFFRepresentation];
  unsigned int length = [tiffData length];

  char * iconBuff = new char[length];
  [tiffData getBytes:iconBuff length:length];

  Nan::MaybeLocal<v8::Object> ret = Nan::NewBuffer(iconBuff, length);

  return ret;
}

这是我根据@uliwitness 的回答最终使用的具体代码:

Nan::MaybeLocal<v8::Object> getIconForFile(const char * str) {
  @autoreleasepool {
    NSImage * icon = [[NSWorkspace sharedWorkspace] iconForFile:[NSString stringWithUTF8String:str]];
    NSData * tiffData = [icon TIFFRepresentation];
    unsigned int length = [tiffData length];

    return Nan::CopyBuffer((char *) [tiffData bytes], length);
  }
}

这似乎是最优雅的解决方案,并且从一些快速而肮脏的测试来看,似乎在多次调用后 node.js 中的驻留集大小较小,无论其价值如何。

我在谷歌上搜索了关于 Nan::NewBuffer 的文档,并找到了这个页面:https://git.silpion.de/users/baum/repos/knoesel-mqttdocker-environment/browse/devicemock/node_modules/nan/doc/buffers.md

这表示:

Note that when creating a Buffer using Nan::NewBuffer() and an existing char*, it is assumed that the ownership of the pointer is being transferred to the new Buffer for management. When a node::Buffer instance is garbage collected and a FreeCallback has not been specified, data will be disposed of via a call to free(). You must not free the memory space manually once you have created a Buffer in this way.

所以你自己的答案中的代码是不正确的,因为使用 new char[] 创建的缓冲区需要使用 delete [] 处理(这与 delete,FWIW 不同),但是你将它交给了一个承诺调用 free 的函数。您只是不小心关闭了错误消息,而不是修复错误。

所以至少,你应该在那里使用 malloc 而不是 new

此页面还提到了另一个函数 Nan::CopyBuffer(),它被描述为:

Similar to Nan::NewBuffer() except that an implicit memcpy will occur within Node. Calls node::Buffer::Copy(). Management of the char* is left to the user, you should manually free the memory space if necessary as the new Buffer will have its own copy.

这听起来是您原始代码的更好选择。您可以将 NSDatabytes 传递给它,它甚至会为您进行复制。您不必担心 "manually freeing the memory space",因为内存由 NSData 拥有,它会在释放时处理它(如果您使用的是 ARC,ARC 将释放 NSData,如果你不是 ARC,你应该添加一个 @autoreleasepool 以便它被释放)。

PS - 在该页面的底部,它还提到您可以使用 Nan::FreeCallback 并将其传递给 Nan::NewBuffer。如果您在那里提供一个在给定的缓冲区上调用 delete [] 的代码,那么您答案中的代码也可以使用。但实际上,为什么要为某些 Nan::CopyBuffer 显然已经为您完成的事情编写额外的代码?