[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


  • Mod

    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


  • Mod

    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


  • Mod

    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


Anmelden zum Antworten