2009-07-14 6 views
3

Sollte es möglich sein, dass gc.get_referrers (obj) eine leere Liste für ein Objekt zurückgibt, das Objekt aber dennoch über eine schwache Referenz zugänglich ist?Python-Objekt hat keine Referrers, aber immer noch über eine Schwachstelle erreichbar?

Wenn ja, wie würde ich anfangen zu versuchen, die Ursache für dieses Objekt nicht Müll gesammelt zu identifizieren?

Edit: Ich bin mir nicht sicher, wie genau ein Codebeispiel in diesem Fall helfen würde - es gibt offensichtlich eine starke Referenz irgendwo, aber ich werde verdammt sein, wenn ich es finden kann. Ich hatte den Eindruck, dass alle starken Referenzen auf ein Objekt von get_referrers() identifiziert werden.

Bearbeiten: Gelöst. Ich habe die Variable mit einer starken Referenz gefunden - sie befand sich innerhalb der Spiel-Ereignisschleife, war aber keine Klassenvariable, also hat get_referrers sie nicht aufgenommen.

+0

bitte einem einfachen Code Beispiel. Ansonsten ist nicht klar, was du meinst. Ist die schwache Referenz selbst zugänglich oder ist das referenzierte Objekt selbst über den weakref zugänglich? – yairchu

+0

Wie haben Sie die Variable mit der Referenz gefunden? Ich versuche gerade ein solches Leck aufzuspüren, aber es ist intermittierend und gc.get_referrers kehrt zurück []. Gibt es eine Möglichkeit zu finden, wo der "lokale" Verweis auf das Objekt ist? – papercrane

Antwort

1

Ja: http://docs.python.org/library/weakref.html

Ein schwacher Verweis wird nicht das Objekt lebendig werden zu halten.

Die Funktion get_referrers() sucht nur solche Container, die die Garbage Collection unterstützen. Erweiterungstypen, die sich auf andere Objekte beziehen, aber die Garbage Collection nicht unterstützen, werden nicht gefunden.

Was lässt Sie denken, dass das Objekt nicht gesammelt wird? Haben Sie auch gc.collect() ausprobiert?

+0

Ich bekomme immer noch eine Objektinstanz durch meine Schwachstelle, wenn ich eine None erwarte. –

+1

Sind Sie sicher, dass es anderswo keine starke Referenz gibt? Auch die Speicherbereinigung ist nicht automatisch (selbst bei Ref-Zählen, wenn es einen Zyklus von Referenzen gibt, werden diese warten, bis ein anderer Speicherbereinigungsalgorithmus verwendet wird) –

+0

Ja, aber für wie lange? Für immer? dh Sie lassen das Programm für eine lange Zeit laufen, und das Objekt sammelt nie? Pythons GC ist generationsübergreifend, daher kann es einige Zeit dauern, bis das Objekt gesammelt ist. – Christopher

0

Wie Christopher says zählt ein schwacher Verweis nicht in object refcount, und daher kann Python kein Objekt löschen.

Pythons Garbage Collector löscht jedoch keine Objekte, die sich in einer Zirkelreferenz befinden und eine __del__-Methode definiert haben.
Sie können diese Situation überprüfen (und beheben), indem Sie gc.garbage verwenden.

+0

gc.garbage ist eine leere Liste nach dem Aufruf von gc.collect() - weder das Objekt noch seine Oberklassen definieren __del__. Wären Kreisreferenzen durch die von gc.get_referrers() zurückgegebene Liste identifizierbar? –

0

Wenn Sie eine starke Referenz auf das Objekt haben, verwenden Sie gc.get_referrers (obj), um es zu finden.

Dies kann helfen, wenn Sie ein Leck haben und nicht wissen, was undicht:

http://mg.pov.lt/objgraph.py http://mg.pov.lt/blog/hunting-python-memleaks http://mg.pov.lt/blog/python-object-graphs.html

Es ist eine dünne Hülle um das Modul überprüfen; Es kann sehr hilfreich sein, wenn Sie unerwünschte Referenzen schwer aufspüren. Um jedoch nur eine Referenz zu finden, benötigen Sie wahrscheinlich nur gc.get_referrers.

1

Es könnte auch der Fall sein, dass eine Referenz durch eine fehlerhafte C-Erweiterung geleakt wurde, IMHO wird der Referer nicht angezeigt, aber der refcount geht nicht auf 0 zurück. Sie können den Rückgabewert von sys.getrefcount überprüfen .

1

Ich bin froh, dass Sie Ihr Problem gefunden haben, unabhängig von der ersten Frage. Dennoch habe ich eine andere Antwort auf die Nachwelt, falls andere das Problem haben.

Es ist legal, dass das Objekt keine Referrer hat und trotzdem keine Garbage Collections sein.

Aus dem Python 2.7 Handbuch: "Eine Implementierung darf Garbage Collection verschieben oder ganz weglassen - es ist eine Frage der Implementierungsqualität, wie Garbage Collection implementiert wird, solange keine Objekte erfasst werden, die noch erreichbar sind."

Der NO-OP-Garbage Collector ist legal.

Die Diskussionen über die Generationen und Referenzzählung Müllsammler beziehen sich auf eine bestimmte CPython Implementierung (wie in der Frage getaggt)