在这种情况下,为什么闭合会导致JavaScript中的内存泄漏?
我有以下代码段:
function outer() {
let a
return function inner() {
a = new Uint8Array(100000)
const b = new Uint16Array(100000)
};
};
const fn = outer();
fn()
拍摄了一个堆快照,在大约:chrome 103.0.5060.114中的空白页面上运行,并拍摄了第二个快照。比较了两个快照,我发现在第二个快照中,有一个 uint8array
。这意味着a
保留在内存中,因此泄漏。但是我找不到任何uint16Array
SO b
没有泄漏。
,但我无法弄清楚为什么uint8array
泄漏,因为它似乎没有就像我仍然可以在外部
函数之外引用它。因此,根据垃圾收集算法的说法,现在应该已经收集了它。
尚未在其他浏览器或节点中对此进行测试。
I have this following code snippet:
function outer() {
let a
return function inner() {
a = new Uint8Array(100000)
const b = new Uint16Array(100000)
};
};
const fn = outer();
fn()
Took one heap snapshot, ran it in a about:blank page in chrome 103.0.5060.114, and took a second snapshot. Comparing the two snapshots, I found that in the second snapshot, there is one more Uint8Array
. That means a
is retained in memory, so it leaked. But I can't find any Uint16Array
so b
didn't leak.
But I couldn't figure out why that Uint8Array
is leaking because it doesn't seem like I can still reference it outside the outer
function. So According to the garbage collection algorithm, it should have been collected by now.
Haven't tested this in other browsers or in Node.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
@itgoldman的解释是正确的:
a
由于Inner
使用它而被保留,并且fn ==== Inner
和fn
fn 仍然可以达到。这不是泄漏。a
可以在fn()
完成fn()
fn()之后再次达到。b
只是一个本地变量,因此当fn()
返回时,它会超出范围。一个示例如何有用/
必需它不能收集。
是
Inner
/fn
从a
读取,写入a
还是两者都不重要,这没关系。只要使用a
以任何方式,只要fn
还活着, a 就会保持生命。这是有道理的,因为可能有多个函数参考它:您可以将innect1
分配新数组并将它们存储在a
中,innion2
用这些阵列做事。(这不是V8问题;所有符合规格的JavaScript引擎都必须这样的行为。)
@ITgoldman's explanation is right:
a
is retained becauseinner
uses it, andfn === inner
, andfn
is still reachable. This is not a leak.a
can be reached again afterfn()
finishes simply by callingfn()
again.b
is just a local variable, so it goes out of scope whenfn()
returns.An example how this is useful/required: consider the following slight modification of your snippet:
Clearly,
a
should remain alive from one invocation offn()
to the next, so it can't be collected.It doesn't matter whether
inner
/fn
reads froma
, writes toa
, or does both. As long as it usesa
in any way,a
will remain alive as long asfn
is alive. This makes sense because there could be more than one function referring to it: you could haveinner1
allocating new arrays and storing them ina
, andinner2
doing stuff with these arrays.(This is not a V8 question; all spec-compliant JavaScript engines are required to behave like this.)
您可以详细介绍垃圾收集在关闭中的工作方式在这里。
You can more about how garbage collection works in closures here.