我对内存(不需要的引用)泄漏垃圾收集语言中的内存泄漏感兴趣
由存储的闭包中捕获的变量引起 (可能作为对象系统的一部分,或作为基于稍后要评估的输入构建动作的一部分)。
有没有哪种语言有点普遍?如果是这样,那些语言需要注意哪些模式以防止它?
答案 0 :(得分:3)
只要引用闭包,就会保留捕获的变量。因此,您需要注意创建对这些闭包的引用的位置。
未取消订阅的事件处理程序是许多类型泄漏的潜在来源。但是,我无法想到任何通用模式可以帮助您以各种可能的方式使用闭包:)
答案 1 :(得分:1)
这不是你的意思,而是Internet Explorer中的垃圾收集器< 7用于不能用循环引用收集变量。这与闭包本身没什么关系,但事实证明,javascript中的闭包很容易创建循环引用。
我认为像这样的模式会做
function foo() {
var div = document.getElementById('mydiv');
div.onclick = bar;
function bar() {
div.style.opacity = 0.5;
}
}
现在,无论你做什么,函数bar
都引用变量div
,同时被赋值为div
的属性。
因此,在IE上使用闭包到avoid memory leaks时,有必要特别注意。
答案 2 :(得分:1)
在许多语言中,如果创建多个委托来关闭给定范围内的某些变量,则关闭其中任何变量的每个委托都将关闭所有变量。例如:
Action blah(Dictionary<string, int> dict, List<string> list)
{
int i;
list.ForEach( (st) => if (dict.Contains(st)) i++; );
return () => Console.WriteLine("The value was {0}", i);
}
该方法将创建两个委托。第一个需要变量dict
和i
,并且在函数退出之前将被放弃。第二个只需要i
,但可以由呼叫者无限期保留。只要调用者保留此方法返回的委托,传入的字典就不可收集。
编译器可以通过生成两个闭包来避免此问题,其中一个闭包有dict
和int[1]
,另一个闭包int[1]
;两个闭包都会保存对同一int[1]
的引用,从而保留了所需的语义。但实际上,与超额捕获相关的额外成本。
答案 3 :(得分:0)
Closure中的变量没有被“捕获”但仍然被引用,GC在发布引用之前不会收集它们。当应用程序终止时,任何未完成的闭包都将取消引用并释放任何相关资源。没有内存泄漏,因为释放了所有分配的资源。