Seite 1 von 1

Cyclic Garbage Collection

Verfasst: Montag 9. November 2009, 23:30
von Maple99
Moin,

ich habe mal eine frage zur Auflösung der zyklischen Abhängigkeiten und damit verbundenen Speicherfreigabe. Leider wird nämlich bei mir der Speicher nicht freigegeben (jedenfalls glaube ich das es so ist). Folgende Funktionen habe ich implementiert:

Code: Alles auswählen

static int
My_traverse(MyObject *self, visitproc visit, void *arg) {
    unsigned int i;
    int res = 0;
    for (i = 0; (i < self->len) && (res == 0); ++i) {
        res = visit(self->e[i], arg);
        PySys_WriteStdout("Res = %d\n", res);
    }
    return res;
}

static int
My_clear(MyObject* self) {
    unsigned int i;

    PySys_WriteStdout("Clear");

    for (i = 0; i < self->len; ++i) {
        Py_CLEAR(self->e[i]);
    }
    return 0;
}
static void
My_dealloc(MyObject *self) {
    My_clear(self);
    Py_TYPE(self)->tp_free((PyObject*) self);
    PySys_WriteStdout("%s", "fertig\n");
}

Wenn ich eine zyklische Verkettung einbaue und danach "del myVar" aufrufe, dann erscheint der Text "fertig" nicht, so dass ich annehme das das dealloc nicht ausgeführt wird. Wenn ich den Interpreter verlasse erscheint die "Res-Ausgabe" 2*self->len Mal, aber der Wert ist immer 0. Eigentlich sollte er doch mal <> 0 sein, wenn die visit-function einen Zyklus entdeckt hat. Leider scheint sie den nicht zu finden, denn ich sehe keine "Clear" und keine "Fertig"-Ausgabe ;(
Hat jemand vielleicht einen Tip für mich woran es liegen kann?

Gruß

Jonny

P.s. Im TypeObject sind dealloc, traverse und clear registriert und Py_TPFLAGS_HAVE_GC ist gesetzt.

Verfasst: Dienstag 10. November 2009, 08:18
von BlackJack
@Maple99: Wie und wo führst Du den ``del myVar`` aus? Bist Du sicher, dass es danach wirklich keine Referenz mehr auf das Objekt gibt?

Verfasst: Dienstag 10. November 2009, 17:46
von Maple99
Hi,

also ich führe folgenden Code im Interpreter aus:

Code: Alles auswählen

from MyModule import *
# 5 ist die Anzahl der Elemente in e
a = MyType(5)
a = a.add(a)
del a
Jetzt sollte ja eigentlich der Speicher aufgeräumt werden, aber es passiert wie gesagt leider nichts. Wenn ich statt a eine Zahl oder ein anderes Objekt "adde" dann wird alles korrekt aufgeräumt.

Gruß

Jonny

Verfasst: Sonntag 15. November 2009, 21:23
von Maple99
Hi,

hat vielleicht irgendjemand noch mal einen Tip wo ich noch mal schauen kann??

Verfasst: Sonntag 15. November 2009, 21:30
von derdon
Maple99 hat geschrieben:Jetzt sollte ja eigentlich der Speicher aufgeräumt werden, aber es passiert wie gesagt leider nichts.
del räumt nicht den Speicher auf, es wird lediglich der Name, der auf das Objekt verweist, entfernt (aber nicht das Objekt selbst!).
http://docs.python.org/reference/simple_stmts.html#the-del-statement hat geschrieben:Deletion of a name removes the binding of that name from the local or global namespace, depending on whether the name occurs in a global statement in the same code block.

Verfasst: Sonntag 15. November 2009, 21:40
von Maple99
Hi,

okay danke für die Antwort, aber wie bewege ich den Interpreter denn dazu den Speicher dann bitte auch gleich mal freizugeben??

Gruß

Jonny

Verfasst: Sonntag 15. November 2009, 22:45
von Darii
evtl über ``gc.collect()``

Verfasst: Sonntag 15. November 2009, 22:48
von Maple99
Hi,

danke, das habe ich auch schon mal getestet. Leider ist das so eine Erscheinung das der Garbage Collector den Speicher nur manchmal aufräumt ;(
Kann mir jemand erklären was die visit-Function genau tut bzw. was der Parameter args soll??
Meiner Meinung ist die Python-Doku sehr zurückhaltend mit Details ;(

Verfasst: Sonntag 15. November 2009, 23:45
von BlackJack
@Maple99: Ich denke mal das braucht man an der Stelle einfach nicht zu wissen. Und wenn man es doch wissen möchte -- der Quelltext ist ja verfügbar.

Wenn ich mal raten müsste, dann sorgt die Funktion dafür, dass bei den übergebenen Objekten ebenfalls die `traverse`-Funktion aufgerufen wird, und das `args` auf eine Struktur verweist, in der aufgezeichnet wird, welche Objekte schon besucht wurden. Eben um Kreise in dem Objektgraphen zu finden.

Bist Du ganz sicher, dass es keine Referenz mehr auf das Objekt gibt? Beliebte "Fallen" sind zum Beispiel der Name `_` im interaktiven Python-Shell oder bei `ipython` *alles* was mal als Ergebnis in einer Sitzung kam, oder die letzte Ausnahme, die vielleicht noch über irgendeinen Stackframe eine Referenz hält.

Verfasst: Sonntag 15. November 2009, 23:48
von Darii
gibt am besten mal ein *komplettes* Minimalbeispiel mit allen notwendigen Sourcen an.