要求错误导致内存泄漏

require error causes memory leak?

本文关键字:内存 泄漏 错误      更新时间:2023-09-26

我有以下程序,它不断增长它的堆。 这是一个非常简单的程序,通过require重复加载外部文件(SyntaxError)。由于外部模块中的语法错误,无法加载。

我运行节点垃圾收集器和转储堆大小以查看内存是否泄漏。如果我修复外部文件(SyntaxError.js)中的语法错误,那么泄漏就会消失,并且在一百万次迭代后内存使用量保持不变。

使用节点版本:0.10.29 和--expose-gc

任何关于可能发生的事情以及如何避免内存泄漏的见解将不胜感激。

测试代码:

(function() {
  var MAX_ITER_COUNT, MEGABYTE, dumpMem, gc, iterCount, noop, peakMem, test2;
  iterCount = 0;
  MAX_ITER_COUNT = 1000 * 1000;
  peakMem = 0;
  MEGABYTE = 1024 * 1024;
  noop = function() {};
  dumpMem = function() {
    var currentMem;
    currentMem = Math.round(process.memoryUsage().heapUsed / MEGABYTE);
    if (currentMem > peakMem) {
      peakMem = currentMem;
    }
    return console.log("" + iterCount + " - memory is: " + currentMem + "/" + peakMem + " MB");
  };
  gc = function() {
    return global.gc();
  };
  process.on("uncaughtException", function(err) {
    return console.log("Unhandled exception! ", err, err.stack);
  });
  test2 = function() {
    var e;
    iterCount++;
    try {
      /*
      Load a module that has a syntax error to create mem leak, and ignore exception
      */
      require("./SyntaxError");
    } catch (_error) {
      e = _error;
    }
    gc();
    dumpMem();
    return setTimeout(test2, 0);
  };
  test2();
}).call(this);

和语法错误.js:

(function() {
  'use strict';
  /* y does not exist, and results in exception*/
  var x;
  x = y;
}).call(this);

似乎这是一个节点错误。 我可以通过将 try/catch 放在 SyntaxError.js 的主体周围来解决这个问题.js。 我的测试,从上面简化:

mem-leak-bug.js:

for (i=0; i<1000000; i++) {
    try {
        require('./mem-leak--error.js');
    }
    catch (e) { }
    if (i % 1000 === 0) {
        global.gc();
        console.log(i, process.memoryUsage().heapUsed/1e6|0, process.memoryUsage().heapTotal/1e6|0);
    }
}

内存泄漏错误.js:
注意:catch 块中必须有一个显式返回,否则也会泄漏内存

// throw an undefined variable exception
try {
    return x;
}
catch(e) {
    return;
}

如果没有 try-catch,它会泄漏内存:

% node --expose-gc ar/mem-leak-bug.js
0 1 5
1000 2 14
2000 2 14
3000 3 14
4000 3 23
5000 3 23
6000 4 24

使用 SytaxError 中的 try-catch,它不会:

% node --expose-gc ar/mem-leak-bug.js
0 1 5
1000 1 7
2000 1 7
3000 1 7
4000 1 7
5000 1 7
6000 1 7
7000 1 7
8000 1 7