Ressourcenmüll wurde zu früh gesammelt

9

Ich habe mit SWIG eine PHP-Erweiterung erstellt, und alles funktioniert gut, aber ich beobachte ein seltsames Garbage Collection-Verhalten beim Verketten Methodenaufrufe. Zum Beispiel funktioniert das:

%Vor%

Aber dieser seg Fehler:

%Vor%

Der einzige Unterschied ist, dass der erste $results erstellt, während der zweite die Aufrufe zusammenfasst.

SWIG stellt Funktionen nur PHP zur Verfügung und generiert PHP-Proxy-Klassen, um mit ihnen zu interagieren. Diese Proxy-Klassen enthalten im Wesentlichen eine Ressource, die an jede der exponierten Funktionen gemeinsam mit allen anderen Argumenten übergeben wird, die diese Funktionen normalerweise annehmen würden. Da ich dachte, dass diese Proxy-Klassen vielleicht das Problem waren, habe ich den Code überarbeitet, um sie zu umgehen und stattdessen die exponierten Funktionen direkt zu verwenden. Wie zuvor funktioniert das:

%Vor%

Und wieder, diese seg Fehler:

%Vor%

Wiederum besteht der einzige Unterschied darin, dass der erste $results erstellt, während der zweite die Aufrufe zusammenfasst.

An diesem Punkt habe ich eine Weile mit gdb / valgrind debuggen müssen und festgestellt, dass der Destruktor, für den InvocationResponse_results zurückgibt, zu früh aufgerufen wird, wenn Aufrufe zusammen verkettet werden. Um zu beobachten, habe ich std::cout -Anweisungen an die Spitze der exponierten C ++ - Funktionen und deren Destruktoren eingefügt. Dies ist die Ausgabe ohne Verkettung:

%Vor%

Ich habe --- am Ende des Skripts ausgedruckt, um unterscheiden zu können, was während der Ausführung des Skripts passiert und was danach passiert. Hola Mundo stammt von printf . Der Rest stammt aus C ++. Wie Sie sehen können, wird alles in der erwarteten Reihenfolge aufgerufen. Destruktoren werden erst nach der Ausführung des Skripts aufgerufen, obwohl der TableIterator Destruktor früher aufgerufen wird, als ich erwartet hätte. Dies hat jedoch keine Probleme verursacht und ist wahrscheinlich nicht damit verbunden. Vergleichen Sie dies nun mit der Ausgabe mit Verkettung:

%Vor%

Ohne den Rückgabewert von InvocationResponse_results , der in $results gespeichert wird, wird glücklich Müll gesammelt, bevor die Ausführung sogar aus der Aufrufkette herauskommt (zwischen Tables_get und Table_iterator ) und dies verursacht schnell Probleme auf der Straße was letztendlich zu einem seg-Fehler führt.

Ich habe auch Referenzzählungen mit xdebug_debug_zval() an verschiedenen Stellen untersucht, aber nichts Ungewöhnliches festgestellt. Hier ist seine Ausgabe auf $results und $row ohne Verkettung:

%Vor%

Und bei $row mit Verkettung:

%Vor%

Ich habe jetzt ein paar Tage damit verbracht und ich habe gerade keine Ideen mehr, also wäre wirklich jede Einsicht, wie man das lösen könnte, sehr willkommen.

    
Ed Mazur 19.08.2010, 20:44
quelle