首页 > 解决方案 > eval() JavaScript 内存泄漏

问题描述

我有一个私人客户端将我的服务器 javascript 作为要执行的字符串发送。这是按预期工作的,但是,每次我将 JS 的有效负载发送到服务器时,内存都会增加,但我的内存使用量永远不会下降。

这是 node.js 代码:

app.post(`/`, (req, res) => {
  const final = req.body.toString();
    function executeJS(str) {
    return new Function(`'use strict'; ${str}`)();
  }
  res.status(200).json(executeJS(code)).end();
});

我附上了我的内存使用情况的截图。你可以猜到,就在 8 点 45 分左右,我向服务器发送了几个请求。处理请求后,内存会上升并继续保持该级别。

内存使用情况

标签: javascriptnode.jsexpressmemory-leakseval

解决方案


是的。这将是它的工作方式。Javascript 代码(一旦在 nodejs 中加载和编译)不会被垃圾收集,因此您以这种方式运行的代码越多,您的进程将存储的代码就越多。

为了安全、安全和内存管理,您可以在 child_process 或 WorkerThread 中运行此代码,然后不时回收(销毁和重新创建)该子进程或 worker 以摆脱旧代码。

此外,在查找内存泄漏时,不能仅仅因为内存使用量上升并保持不变就判断泄漏。只有当内存使用量随着时间的推移不断增加时,才会证明内存泄漏。内存增加但没有回退的情况可能是一个进程没有将未使用的内存返回给操作系统,但该内存可在进程中重用。这不会是真正的泄漏。因此,您还必须确保有实际泄漏。

但是,您所描述的不断运行越来越多的代码的情况在我看来确实会造成像泄漏这样的情况,即消耗越来越多的内存。这种使用模式并不是 node.js 专门设计的。因此,您必须使用诸如 WorkerThread(它是一个单独的 V8 实例)或一个子进程(也是一个单独的 V8 实例)之类的解决方法,您可以每隔一段时间对其进行核对以回收旧代码使用的内存。


我还要补充一点,让服务器接受来自外部世界的代码并在您的主服务器进程中“运行”它是非常不寻常的。正如其他人所提到的,无论您采取何种预防措施,这种架构都存在各种安全漏洞。发送数据然后运行处理数据的代码,或者如果你真的必须接受来自外部世界的未知代码然后在另一个进程中运行它,甚至可能是一个沙盒进程来保护服务器免受任何它的影响,这种情况更为常见可能会 - 无论是意外崩溃、意外错误(如死while循环)还是做一些恶意的事情。


推荐阅读