为何Node.js中无限循环创建全局变量无法耗尽堆内存?
为什么你的代码耗不尽Node.js堆内存?怎么改?
原因分析
你这段代码跑很久都不触发内存错误,核心有两个关键点:
- 字符串驻留优化:你给每个变量赋值的都是完全相同的字符串
"I will break you.",V8引擎会自动对重复字符串做驻留处理——内存里只保留一份该字符串的实例,所有变量都指向这同一个实例,不会重复占用内存。 - 全局属性内存占用极低:用
var创建的全局变量本质是给global对象添加属性,每个属性条目本身仅占用极小的内存(比如存储键名和指针),要堆积到耗尽堆内存需要创建数亿甚至数十亿个变量,自然需要运行极长时间。
修改方案
要快速耗尽堆内存,核心是让每个变量占用独立且足够大的内存空间,以下是两种高效的实现方式:
方案一:生成唯一的大字符串
通过让每个变量的字符串值唯一且足够长,避免V8的字符串驻留优化:
for (let i = 0; true; i++) { eval(`var a${i} = "I will break you.".repeat(10000) + ${i}`); }
这里用repeat(10000)放大字符串体积,追加i保证每个字符串唯一,V8无法复用内存,每个变量都会占用独立的大块内存。
方案二:直接创建大数组/对象(更高效)
没必要用eval,直接给global对象添加属性并赋值大内存对象,避免代码解析的额外开销:
let i = 0; while (true) { global[`a${i}`] = new Array(100000).fill('x'); // 每个数组占用大量独立内存 i++; }
这种方式会快速占用堆内存,很快就能触发内存溢出错误。
另外补充:你对var创建全局变量的理解是对的,问题不在作用域,而在变量值的内存复用机制。
内容的提问来源于stack exchange,提问作者JCollier
相关产品推荐
相关产品推荐

