5

Ich habe eine JavaScript-Speicherbereinigung/Speicherleck Frage. Ich verwende Chrome 28.0.1500.71 unter OS X 10.8.4.JavaScript Closure Memory Leak

Der folgende Code wird niemals den Speicherplatz freigeben, der von me gehalten wurde, und ich weiß nicht warum.

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 scheint das Objekt durch den Ausdruck new MyClass() (das Objekt, das me zeigten auf, bevor null gesetzt wird) geschaffen zu halten im Speicher, da es durch self im Aufruf von me.do_thing() verwiesen wird. Allerdings hätte ich gedacht, der Anruf an destroy(), die me.do_thing Unsets wegwerfen würde die Variablen im Rahmen des Konstruktors wegwerfen (self in der new MyClass() Anruf).

Ich habe auch versucht, Underscore.JS _.bind Funktion zu verwenden, aber laufen in das gleiche ungelöste Problem wie hier beschrieben: Instances referenced by 'bound_this' only are not garbage collected.

+0

Bitte seien Sie präzise und unterscheiden Sie zwischen der globalen Variable 'me' und dem' MyClass' Objekt. Die Variable wird sicherlich im Speicher bleiben, aber das ist kein Problem (und wenn es ist, können Sie es aus 'Fenster 'entfernen, siehe Simonleung's Antwort). Zeigt Chrome an, dass das 'MyClass'-Objekt noch am Leben ist? – delnan

+0

Messepunkt; es ist das 'MyClass'-Objekt, auf das * von mir verwiesen wurde, das niemals freigegeben wird. Ich habe den Wortlaut meiner Frage aktualisiert, um dies klarer zu machen. – soney

+1

Sieht so aus, als gäbe es einen Fehler in V8, ich öffnete ein Problem dagegen: https://code.google.com/p/v8/issues/detail?id=2791 –

Antwort

0

ich ist immer noch eine Eigenschaft von Fensterobjekt, auch wenn Sie es auf null setzen. So ist "ich" immer noch in der Erinnerung.

ich denke, das helfen kann:

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

Dieses Schnipsel lässt immer noch das 'MyClass'-Objekt in zugewiesen mein Browser. – soney

1

Ich weiß nicht, warum es nicht Müll gesammelt, aber das Hinzufügen der Methode auf die Instanz zerstören anstelle des Prototyps und Einstellung self auf null, wird offenbar arbeiten :

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; 
+0

Interessant, obwohl ich immer noch neugierig bin, warum 'self' manuell entsorgt werden muss – soney

+0

@soney es scheint, als ob es etwas mit der Zuweisung von' self.x' in der Zeile 'self.x ++' zu tun hat. Wenn Sie diese Zeile in 'return self.x' ändern, wird auch Müll gesammelt. – basilikum

0

MyClass ist eine globale Variable. Es ist auch eine Eigenschaft eines Fensterobjekts in der Browserumgebung. Es ist kein Müll, also wird es natürlich nicht gesammelt.

+0

Während die 'MyClass'-Funktion Platz beansprucht, verweise ich auf das Objekt, das mit dem Ausdruck' new MyClass() 'erstellt wurde. Nachdem 'me' auf null gesetzt wurde, sollte es keine Referenzen mehr haben und sollte gesammelt werden. – soney

+0

das Objekt wird von der GC gesammelt, nur nicht sofort. Versuchen Sie, einen neuen Heap-Snapshot zu aktualisieren, und generieren Sie kein MyClass-Objekt. – simonleung

0

Sieht aus wie ein Fehler. Btw me.destroy() ist nicht notwendig. Es sollte ohne es gelöscht werden.