NodeJS / node-ffi:内存泄漏/variables范围

我正在调查我的nodejs脚本中的内存泄漏。

请考虑下面的代码块(整个源代码将在底部)。 GetImage调用一个C函数来分配一个缓冲区,并且调用者有责任释放它。 在res.send(data)行后, var dataPtr会在GC期间被释放?

 app.get('/test', function(req, res) { res.contentType('image/jpeg'); var lengthPtr = ref.alloc('uint'); var dataPtr = ref.alloc('uchar*'); lib.GetImage(dataPtr, lengthPtr); var length = lengthPtr.deref(); var data = ref.reinterpret(ref.deref(dataPtr), length); res.send(data); }); 

处理大约20000个请求后出现错误消息:

 Error: reinterpret: Cannot reinterpret from NULL pointer at Object.reinterpret (/home/ltse/LinuxPort/Experiments/NodeAddon/node_modules/ref/lib/ref.js:773:21) at Object.handle (/home/ltse/LinuxPort/Experiments/NodeAddon/ffi.js:20:17) at next_layer (/home/ltse/LinuxPort/Experiments/NodeAddon/node_modules/express/lib/router/route.js:103:13) at Route.dispatch (/home/ltse/LinuxPort/Experiments/NodeAddon/node_modules/express/lib/router/route.js:107:5) at /home/ltse/LinuxPort/Experiments/NodeAddon/node_modules/express/lib/router/index.js:213:24 at Function.proto.process_params (/home/ltse/LinuxPort/Experiments/NodeAddon/node_modules/express/lib/router/index.js:284:12) at next (/home/ltse/LinuxPort/Experiments/NodeAddon/node_modules/express/lib/router/index.js:207:19) at Layer.expressInit [as handle] (/home/ltse/LinuxPort/Experiments/NodeAddon/node_modules/express/lib/middleware/init.js:23:5) at trim_prefix (/home/ltse/LinuxPort/Experiments/NodeAddon/node_modules/express/lib/router/index.js:255:15) at /home/ltse/LinuxPort/Experiments/NodeAddon/node_modules/express/lib/router/index.js:216:9 ...same error message repeated many times... Error: reinterpret: Cannot reinterpret from NULL pointer at Object.reinterpret (/home/ltse/LinuxPort/Experiments/NodeAddon/node_modules/ref/lib/ref.js:773:21) at Object.handle (/home/ltse/LinuxPort/Experiments/NodeAddon/ffi.js:20:17) at next_layer (/home/ltse/LinuxPort/Experiments/NodeAddon/node_modules/express/lib/router/route.js:103:13) at Route.dispatch (/home/ltse/LinuxPort/Experiments/NodeAddon/node_modules/express/lib/router/route.js:107:5) at /home/ltse/LinuxPort/Experiments/NodeAddon/node_modules/express/lib/router/index.js:213:24 at Function.proto.process_params (/home/ltse/LinuxPort/Experiments/NodeAddon/node_modules/express/lib/router/index.js:284:12) at next (/home/ltse/LinuxPort/Experiments/NodeAddon/node_modules/express/lib/router/index.js:207:19) at Layer.expressInit [as handle] (/home/ltse/LinuxPort/Experiments/NodeAddon/node_modules/express/lib/middleware/init.js:23:5) at trim_prefix (/home/ltse/LinuxPort/Experiments/NodeAddon/node_modules/express/lib/router/index.js:255:15) at /home/ltse/LinuxPort/Experiments/NodeAddon/node_modules/express/lib/router/index.js:216:9 FATAL ERROR: Malloced operator new Allocation failed - process out of memory 

NodeJS的源代码:

 var memwatch = require('memwatch'); var express = require('express'); var app = express(); var ref = require('ref'); var ffi = require('ffi'); var lib = ffi.Library('libsample', { 'GetImage' : ['int', ['uchar **', 'uint *']] }); app.get('/test', function(req, res) { res.contentType('image/jpeg'); var lengthPtr = ref.alloc('uint'); var dataPtr = ref.alloc('uchar*'); lib.GetImage(dataPtr, lengthPtr); var length = lengthPtr.deref(); var data = ref.reinterpret(ref.deref(dataPtr), length); res.send(data); }); var server = app.listen(3000, function(){ console.log('Listening on port 3000.'); }) // memwatch console.log('Monitoring memory usage...'); memwatch.on('leak', function(info){ console.log(info); }); memwatch.on('stats', function(info){ console.log(info); }); 

C共享库的源代码:

 #include "sample.h" #include <stdio.h> #include <stdlib.h> int GetImage(unsigned char** data, unsigned int * length) { FILE *fp; unsigned int lSize; unsigned char *buffer; fp = fopen("***PATH TO JPG FILE***", "rb"); fseek( fp , 0L , SEEK_END); lSize = ftell( fp ); rewind( fp ); buffer = calloc( 1, lSize+1 ); fread( buffer, lSize, 1, fp); fclose(fp); *data = buffer; *length = lSize; return 0; } 

命令来build立共享库:

 gcc -g -c -Wall -Werror -fpic sample.c gcc -shared -g -o libsample.so sample.o 

我使用了Apache的基准testing工具来使程序崩溃:

 ab -n 120000 -c 4 http://localhost:3000/test