关闭内存泄漏

时间:2011-03-09 11:46:41

标签: memory-management memory-leaks garbage-collection closures

我对内存(不需要的引用)泄漏垃圾收集语言中的内存泄漏感兴趣

由存储的闭包中捕获的变量引起 (可能作为对象系统的一部分,或作为基于稍后要评估的输入构建动作的一部分)。

有没有哪种语言有点普遍?如果是这样,那些语言需要注意哪些模式以防止它?

4 个答案:

答案 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);
}

该方法将创建两个委托。第一个需要变量dicti,并且在函数退出之前将被放弃。第二个只需要i,但可以由呼叫者无限期保留。只要调用者保留此方法返回的委托,传入的字典就不可收集。

编译器可以通过生成两个闭包来避免此问题,其中一个闭包有dictint[1],另一个闭包int[1] ;两个闭包都会保存对同一int[1]的引用,从而保留了所需的语义。但实际上,与超额捕获相关的额外成本。

答案 3 :(得分:0)

Closure中的变量没有被“捕获”但仍然被引用,GC在发布引用之前不会收集它们。当应用程序终止时,任何未完成的闭包都将取消引用并释放任何相关资源。没有内存泄漏,因为释放了所有分配的资源。