Javascript 由'引用的实例;绑定此';只有垃圾没有被收集

Javascript 由'引用的实例;绑定此';只有垃圾没有被收集,javascript,google-chrome,memory,memory-leaks,google-chrome-devtools,Javascript,Google Chrome,Memory,Memory Leaks,Google Chrome Devtools,我有一个关于google chrome(版本20.0.1132.47,Ubuntu 11.04 64位)中垃圾收集的问题 在比较堆转储和检查内存泄漏时,我发现了一些从未清理过的实例。通常,这种行为可以追溯到程序员的错误,但在这种情况下,我相当无知 请看下面的屏幕截图 实例'child@610739'仅由属于子实例自身函数的'bound_this'实例引用。因此,据我所知,子实例应该被垃圾收集,因为保持它的唯一其他引用是子实例本身(通过“bound_this”函数) 我使用的是下划线.js“bi

我有一个关于google chrome(版本20.0.1132.47,Ubuntu 11.04 64位)中垃圾收集的问题

在比较堆转储和检查内存泄漏时,我发现了一些从未清理过的实例。通常,这种行为可以追溯到程序员的错误,但在这种情况下,我相当无知

请看下面的屏幕截图

实例'child@610739'仅由属于子实例自身函数的'bound_this'实例引用。因此,据我所知,子实例应该被垃圾收集,因为保持它的唯一其他引用是子实例本身(通过“bound_this”函数)

我使用的是下划线.js“bindAll”实用程序函数(),它映射到chrome()的“native_bind”函数

我是否在这里遗漏了一些显而易见的东西?如果是,有人能解释一下是什么让这些实例保持活力吗

更新:

与此同时,我在chrominium(18.0.1025.168(Developer Build 134367 Linux)Ubuntu11.10)中测试了相同的应用程序,它没有显示这些悬而未决的实例

更新2:
按照Esailijas的提示提供一个JSFIDLE代码段,我创建了一个()来模仿我基本上正在做的事情。不幸的是,运行此小提琴并没有显示我在应用程序中遇到的错误行为。在“A”-实例仍被引用时进行的堆转储看起来有点类似,尽管来自window.o数组的引用使实例保持活动状态:

由于在我的案例(截图1)中缺少这样的引用,我不知道是什么阻止chrome释放这些实例

更新3:
按照loislos的建议启用隐藏属性。结果(其中一个分支被扩展)可以在下面的屏幕截图中看到,但这不会让我走得更远。

我在“将其与类绑定”这一术语中提到了这一点

类方法具有“绑定this”,其中方法体中的this始终绑定到从中提取方法的类实例,而不管该参数实际传递给该方法的是什么(忽略该方法的this参数)

现在,在您的示例中,没有给出示例脚本,因此不能针对问题

我得说如果这不是泄漏

然后使用脚本所绑定的任何对象、类,它将不会调用垃圾,直到类/对象存在,因为此函数与同一对象绑定。。只有在其父对象(与之绑定的对象/类)的作用域结束后,才会对其进行垃圾收集

现在,如果任务完成时循环引用将结束,>>这就像递归的概念一样工作(注意它的概念,不同于)。。因此,结尾将从最后一次通话开始。。反过来。。最内部的呼叫(最新呼叫)将首先释放。。等等

代码必须有缺陷,因为它们不能绑定和定义函数,并且每次都不能重用。。但是,如果它们是绑定的,那么它也应该可以正常工作,并且应该不会泄漏,直到内存占用超出内存池的浏览器限制

我希望这能解释..

您是否使用开发人员工具触发“强制GC”?如果是这样的话,那么这些目标就会持续下去,那么上述研究是有价值的

如果您不是通过开发人员工具触发GC,那么请记住GC引擎的工作方式非常复杂,并且它具有分代收集的概念(使用两代)

可能只是因为您尚未达到触发年轻一代GC所需的阈值,或者对象已被保留到旧一代,但从未触发旧一代GC


不幸的是,开发人员工具似乎没有显示哪一代是GC的。

您怀疑这不是实际的内存泄漏,但chrome的怪异之处是正确的

我最近遇到了同样的问题。IE11将不会将this.func=uu.bind(this.func,this)显示为内存泄漏,而chrome将显示为内存泄漏,即使您按下收集垃圾按钮100次

即使在您使用jsflag运行chrome并公开底层垃圾收集器并调用gc 100次之后,它也会显示出来

要证明它实际上不是chrome的漏洞,一个简单的方法是将浏览器的一个小问题变成一个大问题,并强制引擎采取行动

在已指定绑定函数的实例上,指定一个新属性,如下所示:

target.WhyAmILeaking=新阵列(200000000).join(“YOURNOT”)

在chrome上使用三个快照技术,您将看到堆中的字符串大约为214mb。再次执行任何构造性操作(第二个快照),您将看到堆变为423mb或保持在214mb。如果它保持不变,您就完成了原来的214mb已收集的证明。如果它没有停留在你的破坏性行动(第三个快照),它将返回到214mb,也证明原来的收集

如果它只是停留在423mb,您先生或夫人有泄漏

哦,还有另一群可怜的灵魂,他们遇到了完全相同的情况:


TL;博士使用IE 11检测泄漏。

这里没有看到这一点。最初它们就在那里(堆占用17.32mb,有60000个闭包),我等了几分钟,拍了一个新快照,堆回到6mb,闭包就消失了。您可以修改我的JSFIDLE来重现这种情况吗?您可以向我们展示创建这种情况的代码吗?我并不是真的从调试器的屏幕截图中得到它。我将尝试创建一个小片段来重现这个问题。我创建这种情况的代码是一个相当大的SPA的一部分,因此提取起来并不那么容易。与此同时,我在chrominium(18.0.1025.168(Developer Build 134367 Linux)Ubuntu11.10)中测试了相同的应用程序,它没有显示这些悬而未决的实例