本机 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.
这听起来是您原始代码的更好选择。您可以将 NSData
的 bytes
传递给它,它甚至会为您进行复制。您不必担心 "manually freeing the memory space",因为内存由 NSData 拥有,它会在释放时处理它(如果您使用的是 ARC,ARC 将释放 NSData,如果你不是 ARC,你应该添加一个 @autoreleasepool
以便它被释放)。
PS - 在该页面的底部,它还提到您可以使用 Nan::FreeCallback
并将其传递给 Nan::NewBuffer
。如果您在那里提供一个在给定的缓冲区上调用 delete []
的代码,那么您答案中的代码也可以使用。但实际上,为什么要为某些 Nan::CopyBuffer
显然已经为您完成的事情编写额外的代码?
我正在编写一个如下所示的函数:
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.
这听起来是您原始代码的更好选择。您可以将 NSData
的 bytes
传递给它,它甚至会为您进行复制。您不必担心 "manually freeing the memory space",因为内存由 NSData 拥有,它会在释放时处理它(如果您使用的是 ARC,ARC 将释放 NSData,如果你不是 ARC,你应该添加一个 @autoreleasepool
以便它被释放)。
PS - 在该页面的底部,它还提到您可以使用 Nan::FreeCallback
并将其传递给 Nan::NewBuffer
。如果您在那里提供一个在给定的缓冲区上调用 delete []
的代码,那么您答案中的代码也可以使用。但实际上,为什么要为某些 Nan::CopyBuffer
显然已经为您完成的事情编写额外的代码?