[gelöst] Doppelter Aufruf des Destruktors

Verschiedenes zu Qt
Antworten
mogel
Beiträge: 4
Registriert: 31. Januar 2012 08:17

[gelöst] Doppelter Aufruf des Destruktors

Beitrag von mogel »

Guten Morgen,

lt. Call-Stack ruft der Destruktor sich selber auf. Dabei stürzt natürlich das Programm ab. Im Grunde genommen habe ich keine Ahnung wieso der Destruktor sich selber aufruft. Im Grunde habe ich im Program eine Fläche wo ich nur die einzelnen Widgets wie einen Desktop austausche. Jedesmal wenn ein anderer Desktop angezeigt werden soll, wird der Alte (bis auf Ausnahmen) wieder zerstört. Nur der aktuelle Desktop macht da Probleme, mit allen Anderen (rund 15) funktioniert es.

Die Methode die den Destruktor auslöst ist in der gui.cpp:

Code: Alles auswählen

void Gui::openDesktop(BaseDesktop* desktop) {
    // ggf. ein Display deaktivieren
    if (Gui::display != NULL) openDisplay(NULL);

    // den alten Desktop entfernen (nur bei Wechsel zwischen Home/Menu/Page)
    if (Gui::desktop != NULL) {
        instance->center.removeWidget(Gui::desktop);
        Gui::desktop->hide();
    }

    // den neuen Desktop setzen
    if (desktop != NULL) instance->center.insertWidget(-1, desktop);

    // den alten Desktop löschen - außer Home&Menu&Error
    if (Gui::desktop != NULL) {
        if (Gui::desktop != Homescreen::getInstance()) {
            if (Gui::desktop != MenuScreen::getInstance()) {
                if (Gui::desktop != ErrorDesktop::getInstance()) {
                    delete Gui::desktop;
                }
            }
        }
    }

    // neuen Desktop merken
    Gui::desktop = desktop;
}
Seit Wochen funktioniert es ohne Probleme. Nachdem ich gestern auf dem Desktop noch zwei QPushButtons hinzugefügt habe, habe ich diese Probleme. Einmal alles neu erstellen/kompilieren brachte leider nicht die Lösung :roll:

Hat jemand zufällig einen Ahnung wonach ich suchen kann, damit das wieder funktioniert?

hand, mogel
Dateianhänge
doppelter Destruktor.png
doppelter Destruktor.png (106.34 KiB) 6609 mal betrachtet
Zuletzt geändert von mogel am 21. November 2012 16:40, insgesamt 1-mal geändert.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Doppelter Aufruf des Destruktors

Beitrag von franzf »

Kannst du dir nicht nen anderen Namen für den übergebenen Parameter ausdenken als "desktop" - der ist im Kontext der Klasse schon vergeben und produziert ziemlich viel störenden Code.
Die verschachtelten ifs sind auch besser durch Verknüpfung der einzelnen Bedingungen mit "&&" dargelstellt.
delete desktop;
falls desktop==0 ist übrigens valid, deshalb ist es unnötig auf !=NULL vor einem delete zu prüfen.

Zum eigentlichen Problem kann ich aber mangels Code und komplettem BackTrace nichts sagen. Der Screenshot brint leider gar nichts...

Die Ursache für dein Problem muss übrigens nicht zwangsläufid auf ein doppeltes delete rauslaufen (die Meldung ist dann tatsächlich meistens "double free or delete") - du hast dir vielleicht "nur" denen Heap zerschossen ;)
Oder du stellst sonst irgend welche bösen Sachen mit dienem Speicher an, die laut Standard undefiniertes Verhalten auslösen.
mogel
Beiträge: 4
Registriert: 31. Januar 2012 08:17

Re: Doppelter Aufruf des Destruktors

Beitrag von mogel »

Moin,

unterm Strich war es in der Tat ein zerschossener Heap ? Stack.

Das Erstellen des Desktops selber funktionierte nicht immer. Ca. jeder 100(!) brach mit einem Crash ab. Der Desktop selber wurde seit Wochen hier beim Testen aufgerufen und funktionierte. Die Fehlermeldung mit der abgebrochen wurde war "_int_malloc: Assertion `victim->fd_nextsize->bk_nextsize == victim' failed". Etwas Suche mit Google brachte dann die Antwort das da was zerschossen ist. Ergo habe ich mal den Konstruktor begutachtet.

Orginal:

Code: Alles auswählen

    graphen = new Graph*();
richtig:

Code: Alles auswählen

    graphen = new Graph*[MAXCHANNELS];
blöder, kleiner Fehler :roll:

danke, mogel
ceumern
Beiträge: 28
Registriert: 16. September 2011 11:25

Re: [gelöst] Doppelter Aufruf des Destruktors

Beitrag von ceumern »

Man sollte Pointer auch wirklich nur dort verwenden, wo sie Sinn machen. Ich kenne den Kontext deines Programms nicht aber

Code: Alles auswählen

    graphen = new Graph*[MAXCHANNELS];
sieht nach schlechtem (und dadurch fehleranfälligem) Stil aus...

warum nicht z.B. eine QList<Graph>?

C++ ist zwar sehr mächtig, aber man kann sich damit auch hervorragend in den Fuss schiessen ohne es zu merken. Deswegen Pointer und direkten Speicherzugriff nur dort verwenden, wo es absolut notwendig ist.

Oder als Zitat:

"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup
Antworten