【问题标题】:JavaScript Closure Memory LeakJavaScript 关闭内存泄漏
【发布时间】:2013-07-12 13:53:30
【问题描述】:

我有一个 Javascript 垃圾收集/内存泄漏问题。我在 OS X 10.8.4 上使用 Chrome 28.0.1500.71。

以下代码永远不会释放 me 持有的空间,我不知道为什么。

var MyClass = function() {
    this.x = 1;

    var self = this;
    this.do_thing = function() {
        self.x++;
    };
};
MyClass.prototype.destroy = function() {
    delete this.do_thing;
};

var me = new MyClass();
me.do_thing();
me.destroy();
me = null;

// the MyClass object formerly known as 'me' is still allocated here
// (as evidenced by Chrome's heap profiler)

Chrome 似乎将表达式new MyClass()me 在设置为null 之前指向的对象)创建的对象保留在内存中,因为它在对me.do_thing() 的调用中被self 引用.但是,我原以为调用destroy() 会取消设置me.do_thing 会丢弃构造函数范围内的变量(new MyClass() 调用中的self)。

我也尝试过使用 Underscore.JS 的 _.bind 函数,但遇到了此处描述的相同未解决问题:Instances referenced by 'bound_this' only are not garbage collected

【问题讨论】:

  • 请准确区分“全局变量me”和“MyClass 对象”。该变量肯定会保留在内存中,但这不是问题(如果是,您可以将其从 window 中删除,请参阅 simonleung 的回答)。 Chrome 是否表明 MyClass 对象仍然存在?
  • 公平点;这是me 引用的MyClass 对象,它永远不会被释放。我更新了问题的措辞以使这一点更清楚。
  • 看起来 V8 中存在错误,我为此打开了一个问题:code.google.com/p/v8/issues/detail?id=2791

标签: javascript google-chrome memory-leaks garbage-collection google-chrome-devtools


【解决方案1】:

看起来像一个错误。 顺便说一句 me.destroy() 不是必需的。没有它就应该删除它。

【讨论】:

    【解决方案2】:

    MyClass 是一个全局变量。它也是浏览器环境中窗口对象的一个​​属性。它不是垃圾,所以自然不会被收集。

    【讨论】:

    • 虽然MyClass 函数占用空间,但我指的是由表达式new MyClass() 创建的对象。将me 设置为null 后,不应再有对其的引用,应将其收集。
    • 对象将被 gc 收集,只是不会立即收集。尝试刷新并生成新的堆快照,您将看不到任何 MyClass 对象。
    【解决方案3】:

    我不知道为什么它不是垃圾收集,但是将destroy方法添加到实例而不是原型并将self设置为null,显然会起作用:

    var MyClass = function() {
        this.x = 1;
    
        var self = this;
        this.do_thing = function() {
            self.x++;
        };
    
        this.destroy = function() {
            delete this.do_thing;
            self = null;
        };
    };
    
    var me = new MyClass();
    me.do_thing();
    me.destroy();
    me = null;
    

    【讨论】:

    • 有趣,虽然我还是很好奇为什么self需要手动处理
    • @soney 似乎与self.xself.x++ 行中的分配有关。如果将该行更改为return self.x,它也会被垃圾回收。
    【解决方案4】:

    即使您将其设置为 null,me 仍然是 window 对象的属性。因此,“我”还在记忆中。

    我认为这可能会有所帮助:

    window.me = new MyClass();
    me.do_thing();
    delete window.me;
    

    【讨论】:

    • 这个 sn-p 仍然保留在我的浏览器中分配的 MyClass 对象。
    猜你喜欢
    • 2013-03-29
    • 2011-06-28
    • 2010-11-28
    • 2018-08-26
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    • 2013-05-02
    • 2013-05-17
    相关资源
    最近更新 更多