Qt-Problem mit Speicherverwaltung
-
Hallo,
habe mal wieder angefangen, mich der GUI-Programmierung zu widmen und gleich schon ein seltsames Problem.
Also: Ich hab eine eigene Klasse QEdit, die als Element einen Zeiger auf ein Objekt einer anderen eigenen Klasse BufferBox hat. Im Hauptprogramm erstelle ich lediglich ein Objekt von QEdit und eins von QApplication. Dann ruf ich die exec() Funktion von QApplication ab, die beendet wird, wenn die Methode exit() aufgerufen wird (die ist static). Danach wird also die main() Funktion und damit das Programm beendet. Das führt dazu, daß logischerweise der Destruktor von QEdit aufgerufen wird, in dem u.a. der Zeiger auf das BufferBox-Objekt deleted wird. Dadurch wird dort der Destruktor aufgerufen, soll ja auch so sein, aber jetzt kommt's: Ganz am Schluss, nachdem der Destruktor von QEdit aufgerufen wurde, wird ganz komischerweise nochmal der Destruktor von BufferBox aufgerufen! Ist das eine Eigenart von Qt? Ich mein, das kann eigentlich gar nciht angehen.Wenn ich die Zeile, in der die BufferBox gelöscht wird, extra auskommentiere, erhalte ich folgende Ausgabe:
leaving exec() loop..
QEdit: Destructor
BufferBox: DestructorBin für Ideen sehr dankbar.
Gruß, Doktor Prokt
-
Soweit ich weiß (bin leider allerdings auch nur ein Qt-Frischling) löschen Qt-Objekte ihre "Kinder" im Destruktor mit delete(). Zumindest die Widgets tun das. Falls du also BufferBox als Kind von QEdit anlegst, hast du ein delete() zuviel.
Stefan.
-
Ja, das hab ich auch schon gedacht, aber dann müssten die Destruktoren der anderen GUI-Elemente auch zweimal aufgerufen werden.
BufferBox hat im Konstruktor als Parent-Widget einen QVBox-Zeiger übergeben bekommen. Daß der Destruktor von QVBox das löscht, kann auch nicht sein, denn auch wenn ich die Zeile, in der die QVBox gelöscht wird, auskommentiere, bekomme ich beim Beenden nen Segfault (sprich 2mal Ctor von BufferBox).
Wenn ich mit anderen Versionen von Qt (hab jetzt 4 installiert) kompiliere, gehts auch nicht..
-
...denn auch wenn ich die Zeile, in der die QVBox gelöscht wird, auskommentiere...
Wie soll das gehen? Du kannst nur die Zeile auskommentieren, in der _du_ ein delete() machst. Da aber Qt selbst auch die QVBox löscht (die hat ja auch ein Parent, oder?), kannst du das delete() gar nicht verhindern.
Ich würde an deiner Stelle alle eigenen deletes (von Widgets) mal rauswerfen. Dann kannst du:
1.) Prüfen, ob den Programm jetzt problemlos läuft und
2.) Nachsehen, ob die Destruktoren der eigenen Klassen trotzdem aufgerufen werden.
Falls beides zutrifft, hast du die Lösung: deine eigenen deletes sind der Fehler.Stefan.
-
Hallo Stefan,
es funktioniert ja wunderbar und ohne Seg.fault, wenn ich die deletes der eigenen Klassen rausnehme, wunderbar sogar. Die deletes der Standard-GUI-Elemente bleiben drin. Aber was ist das für ein seltsamer Stil zu programmieren, Objekte eigener Klassen nicht zu löschen?
Gruß
-
Über dieses "Feature" von Qt bin ich anfangs auch gestolpert. (Wie übrigens auch über den Meta Object Compiler.) Nicht nur, daß man selbst kein delete() mehr macht, man ist ja auch gezwungen, alle Widgets mit new() (anstatt z.B. als Instanzvariablen) anzulegen.
Allerdings kann ich auch die Motivation dafür verstehen: Systemfenster löschen ja (zumindest unter Windows) automatisch alle ihre Kinder, wenn sie selbst gelöscht werden. Wie aber will man damit umgehen, wenn man Systemfenster in Klassen kapselt? Ich kann verstehen, daß man darauf kommt, unter diesen Umständen auch die zugehörigen Objekte zu löschen. Trotzdem hätte ich es aber anders gelöst.
Stefan.
-
Hm, ok, das BufferBox Objekt scheint tatsächlich von meiner Hauptklasse gelöscht zu werden, aber warum wird dann beispielsweise die Toolbar nicht gelöscht? Die bekommt als parent widget genauso "this" (also das QEditobjekt) übergeben wie die BufferBox.
-
ok, hat sich nun erledigt, hab gerade im trolltech mailing list archive die definition des QWidget-dtors gesehen... d.h. ja, daß man nur noch toplevel widgets zerstören braucht, hm, ok.