[ungelöst]QT: deleteLater() verursacht "Access violation"
-
Hi,
im Destruktor meiner von QGraphicsObject abgeleiteten Klasse versuche ich die Memberobjekte der Klasse zu löschen:
Konstruktor:
tmpText = new QGraphicsTextItem; Properties = new QDialog(mainWnd); //Properties ist eine selbst erstellte Klasse, abgeleitet von QDialog, allerdings wird nichts relevantes verändert //mainWnd ist eine Instanz von QMainWindow Properties->setAttribute(Qt::WA_DeleteOnClose,false); //Attribut Qt::WA_DeleteOnClose ist false, //also wird der QDialog nicht automatisch nach dem Aufruf //von Properties->close(); gelöscht
Destruktor:
//Code Block 1 if(tmpText != NULL && tmpText->scene() != NULL) //Fehler hier (read access violation at 0x0) { tmpText->scene()->removeItem(tmpText); tmpText->deleteLater(); } // //Code Block 2 if(Properties != NULL) { Properties->close(); if(Properties != NULL) //Fehler hier (read access violation at 0x0) delete Properties; //bzw.: wenn ich die zweite if(Properties != NULL) Abfrage weglasse, dann hier } //
----
Wenn ich Code Block 1 debugge (also Code Block 2 auskommentiere), dann bekomme ich nach während dem Aufruf des Destruktors:Fehler:Exception at 0x61440523, code: 0xc0000005: read access violation at: 0x0, flags=0x0 (first chance)
Der Disassembler beschwert sich dann hier:
Qt5Widgets!QGraphicsItem::scene: 0x61440520 <+0x0000> mov eax,dword ptr [ecx+4] 0x61440523 <+0x0003> mov eax,dword ptr [eax+78h] //Fehler in dieser Zeile
Ich kann den Fehler leider nicht deuten, aber ich habe irgendwo gelesen, dass das auftaucht, wenn ich einen NULL-Zeiger dereferenzieren will.
----
Wenn ich Code Block 2 debugge (also Code Block 1 auskommentiere), dann bekomme ich nach während dem Aufruf des Destruktors:Fehler:Exception at 0x5914b0ba, code: 0xc0000005: write access violation at: 0x1, flags=0x0 (first chance)
Der Disassembler beschwert sich dann hier:
Qt5Core!QMutex::lock: 0x5914b0b0 <+0x0000> push esi 0x5914b0b1 <+0x0001> mov edx,1 0x5914b0b6 <+0x0006> mov esi,ecx 0x5914b0b8 <+0x0008> xor eax,eax 0x5914b0ba <+0x000a> lock cmpxchg dword ptr [esi],edx //Fehler in dieser Zeile
Wie man sieht, habe ich schon versucht, zu überprüfen, ob die Zeiger NULL sind, damit kein NULL-Zeiger dereferenziert wird, was aber leider auch nichts gebracht hat.
Ich versuche das jetzt schon seit einer Woche zu beheben, aber ich kann mit dem Disassembler leider nichts anfangen.
Wisst ihr, was ich da falsch gemacht habe?Mit freundlichen Grüßen,
Thronx
-
Afaik bezieht sich deleteLater auch auf das Parent, welches bei dir 0 ist.
QDialog erzeugst du zwar mit new, aber es hat kein QObject Parent.
-
@phlox81:
Danke für deine Antwort,QDialog hat ein Parent QObject vom Typ QMainWindow, ich hab's vergessen, hier einzutragen, aber ich hab's jetzt editiert.
Also ist das Parent QObject kein NULL-Zeiger, und soweit ich die Qt Documentation richtig gelesen habe, steht nichts davon, dass das Parent Object gelöscht wird (soweit ich weiß nur die Child Objects), sondern nur, dass man deleteLater() auch öfter aufrufen kann, was trotzdem nur zu einem Aufruf von delete führt.
Und wenn ich statt deleteLater() delete benutze, bekomme ich den gleichen Fehler.
Kann es nicht sein, dass z.B. Code Block 1 erst überprüft, ob das Zeigerobjekt 0 ist und dann wird kurz vor dem Löschen in Code Block 1 -von einem anderen Thread aus- das Objekt gelöscht und ein NULL-Zeiger gesetzt?
Ich weiß leider nicht an was es sonst liegen könnte.
Mit freundlichen Grüßen,
Thronx
-
Ist die Frage, ob das deleteLater die Ursache ist, oder der Bug schon viel früher bei dir auftritt.
Wie ist der Callstack, gibt es da evtl. eine Gemeinsamkeit?
-
@phlox81:
Du hast recht, der Fehler liegt an://Code Block 1 if(tmpText != NULL && tmpText->scene() != NULL) //Fehler hier (read access violation at 0x0) // ...
bzw. an:
// ... Properties->close(); if(Properties != NULL) //Fehler hier // ...
Der Call Stack sieht so aus: ( glaub ich zumindest
)
Bei dem Fehler in Code Block 1: (Code Block 1 ist am wichtigsten, ohne den Code ist das Programm nicht lauffähig)Tiefe Funktion Datei/Zeile 0 QWidget::normalGeometry Qt5Widgetsd 0x5c7b7922 1 Bac::~Bac bac.cpp 3 0x13d120f //Zeilen Nummer angepasst 2 VBac::~VBac Influence 0x13e298f 3 VBac::`scalar deleting destructor' Influence 0x13e294f 4 QWidget::normalGeometry Qt5Widgetsd 0x5c7f404b 5 QWidget::normalGeometry Qt5Widgetsd 0x5c7f2305 6 QGraphicsScene::`scalar deleting destructor' Influence 0x13ce7d0 7 QTimer::isSingleShot Qt5Cored 0x5bd989a7 8 QTimer::isSingleShot Qt5Cored 0x5bd91950 9 QWidget::normalGeometry Qt5Widgetsd 0x5c7f75ca 10 QWidget::normalGeometry Qt5Widgetsd 0x5c42291e 11 QWidget::normalGeometry Qt5Widgetsd 0x5c42035a 12 QTimer::isSingleShot Qt5Cored 0x5bd48264 13 QTimer::isSingleShot Qt5Cored 0x5bd4d5e9 14 QTimer::isSingleShot Qt5Cored 0x5bd490e5 15 QTimer::isSingleShot Qt5Cored 0x5bd48d9d 16 QCss::StyleSelector::selectorMatches Qt5Guid 0x5cdb84dd 17 QWindowsGuiEventDispatcher::sendPostedEvents qwindowsguieventdispatcher.cpp 86 0x5a67c014 18 QTimer::isSingleShot Qt5Cored 0x5bdd08d7 19 InternalCallWinProc USER32 0x74f862fa
Und bei dem Fehler in Code Block 2: (Bei Code Block 2 würde, wenn ich den Code weglasse, nur Speicher verschwendet werden)
Tiefe Funktion Datei/Zeile 0 QWidget::normalGeometry Qt5Widgetsd 0x5cbd97cc 1 QWidget::normalGeometry Qt5Widgetsd 0x5cbd9a78 2 Bac::~Bac bac.cpp 13 0x1b1208 //Zeilen Nummer angepasst 3 VBac::~VBac Influence 0x1c298f 4 VBac::`scalar deleting destructor' Influence 0x1c294f 5 QWidget::normalGeometry Qt5Widgetsd 0x5cf6404b 6 QWidget::normalGeometry Qt5Widgetsd 0x5cf62305 7 QGraphicsScene::`scalar deleting destructor' Influence 0x1ae7d0 8 QTimer::isSingleShot Qt5Cored 0x5be389a7 9 QTimer::isSingleShot Qt5Cored 0x5be31950 10 QWidget::normalGeometry Qt5Widgetsd 0x5cf675ca 11 QWidget::normalGeometry Qt5Widgetsd 0x5cb9291e 12 QWidget::normalGeometry Qt5Widgetsd 0x5cb9035a 13 QTimer::isSingleShot Qt5Cored 0x5bde8264 14 QTimer::isSingleShot Qt5Cored 0x5bded5e9 15 QTimer::isSingleShot Qt5Cored 0x5bde90e5 16 QTimer::isSingleShot Qt5Cored 0x5bde8d9d 17 QCss::StyleSelector::selectorMatches Qt5Guid 0x5c6484dd 18 QWindowsGuiEventDispatcher::sendPostedEvents qwindowsguieventdispatcher.cpp 86 0x5a71c014 19 QTimer::isSingleShot Qt5Cored 0x5be708d7
Ich hab jetzt in meinem ersten Beitrag die Fehler-Positionen angepasst, aber ich kann auch mit den Stack Frames nichts anfangen.
Mit freundlichen Grüßen,
Thronx
-
Bei 2 wird Properties niemals NULL sein. Was macht close?
-
@phlox81:
Du hast Recht, nur wollte ich sicher gehen, dass kein NULL-Zeiger dereferenziert wird, da ich ja auch dort den "read access violation at 0x0"-Fehler bekomme.QWidget::close() schließt bei mir ein Fenster, das von dem zu zerstörenden Objekt Informationen lieferte.
Allgemein schließt QWidget::close() ein QWidget und hat als Return-Wert true, wenn das Widget tatsächlich geschlossen wurde.
Zusätzlich wird das QWidget dann gelöscht, wenn vorher die Flag Qt::WA_DeleteOnClose mit QWidget::setAttribute() gesetzt wurde, was bei mir aber auch nicht der Fall ist.Mit freundlichen Grüßen,
Thronx