メモリリークは起きない
var hoge = function(){
var x = 0;
return function(){
return x++;
}
}
var h = hoge();
console.log(h());
console.log(h());
console.log(h());
依存しているhの参照が切れた段階でxはガベージコレクタの対象になる
メモリリークは起きない
var hoge = function(){
var x = 0;
return function(){
return x++;
}
}
var h = hoge();
console.log(h());
console.log(h());
console.log(h());
依存しているhの参照が切れた段階でxはガベージコレクタの対象になる
メモリリークは起きる
var hoge = function(){
var x = 0;
process.on('exit', function(){
x++;
});
return function(){
return x;
}
}
var h = hoge();
console.log(h());
console.log(h());
console.log(h());
依存しているhの参照が切れた段階ではxはガベージコレクタの対象にならない
xがnode.jsが動いている限りずっと破棄されないprocessオブジェクトから参照され続けるため。
クロージャーの中でイベントハンドラを登録するときは慎重に。
わかりやすい事例としてsetTimeoutで実行してみる
var leak = function(){
var x = 0;
process.on('exit', function(){
x++;
});
return function(){
return x;
}
}
var update = function(){
var h = leak();
setTimeout(update, 0);
}
update();
node.jsのEventEmitterはデフォルトで10件までしか登録できないようになっているので それを超えるとワーニングが出る。
(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace
at process.addListener (events.js:160:15)
at process.on.process.addListener (node.js:773:26)
at leak (leak.js:9:13)
at update [as _onTimeout] (leak.js:17:13)
at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)