thisptr unter Linux in Destruktor ungültig?



  • Hallo!

    Folgendes Konstrukt:

    CSystem::~CSystem()
    {
    	// this ist valid
    	// this->m_pInformation ist valid und vom Typ CData*
    	this->m_pInformation->DeleteSelf();
    }
    
    // ...
    
    void CData::DeleteSelf()
    {
    	// geht nocht
    	cout << "CData::DeleteSelf wird aufgerufen" << endl;
    
    	// ACHTUNG: Thisptr ist 0?!?!?!
    	cout << "Thisptr: " << this << endl;
    
    	// Crash (Segmention fault), da this ja 0 ist
    	cout << "Root: " << this->m_bRoot << endl;
    
    	if (!this->m_bRoot)
    	{
    		// rekursives löschen
    		this->m_pParent->DeleteSelf();
    	}
    	else
    	{
    		delete this;
    	}
    }
    

    Problem: Es crasht, da der thisptr unverständlicherweise 0 ist. Unter Windows klappt das ganze, unter Linux (Debian Lenny, gcc 4.1.3) nicht. Auch wenn ich es noch so viel betrachte: Ich sehe keinen logischen Fehler?!



  • Wahrscheinlich schlechtes Design, vermeide einfach delete this , da es sehr heikel ist, gerade im Zusammenhang mit deinem Kommentar "rekursives Loeschen". Hast du denn mal debugged und geschaut, wo es genau crashed?



  • Poste mal den gesamten Code.

    Wenn du einen Compilerfehler vermutest: test mal mit einer GCC 3.x Version und mit neueren 4.x versionen (4.5.1).

    Und wie knivil schon angedeutet hat: der Debugger ist dein Freund. Ich sehe keinen Grund warum wir raten sollen, statt dass du mal hergehst und GDB anwirfst.



  • Hi.
    Ich habe nun mal gdb verwendet (zum ersten mal), aber viel mehr sagen als das was ich schon wusste tut er ja auch nicht:

    Program received signal SIGSEGV, Segmentation fault.
    [Switching to Thread 0xf7c866c0 (LWP 26863)]
    0x0804d76d in CData::DeleteSelf (this=0x0)
        at /home/test/CData.cpp:41
    

    Zeile 41 entspricht Zeile 19 aus meinem ersten Post. Der Crash passiert natürlich genau da, da ich auf einen this -ptr zugreife, der den Wert 0 hat.



  • EDIT:

    Ups... War wohl falsch...

    Lass dir

    this->m_pParent
    

    mal ausgeben...

    Der wird vermutlich 0 sein



  • Mhh, drücke ich mich wirklich so schlecht aus?
    Auf m_pParent kann ich gar nicht erst zugreifen, da schon this-> 0 ist. (siehe Zeile 15/16)



  • du löscht aber nicht zufällig von der wurzel zu den blättern 😕



  • Lord_Axiom schrieb:

    Mhh, drücke ich mich wirklich so schlecht aus?
    Auf m_pParent kann ich gar nicht erst zugreifen, da schon this-> 0 ist. (siehe Zeile 15/16)

    Ich rede nicht von deinem Objekt, wo es knallt, sondern von dem Objekt, das
    DeleteSelf(); aufruft. Dort wird m_pParent evtl. schon 0 sein.

    Irgendwo in deinem Code rufst du wahrscheinlich DeleteSelf(); auf einem
    Pointer auf, der auf 0 verweist...



  • Soweit wie ich die undurchsichtige Geschichte verstehe, baut er eine einfach verkettete Liste nach.

    Falls du alles so lassen willst, wie es jetzt ist, hätte ich das Ganze am ehesten in den Destruktor verschoben:

    // void CData::DeleteSelf() // heisst jetzt
    CData::~CData
    {
        if (!this->m_bRoot) {
            // rekursives löschen
            delete this->m_pParent;
        }
        // else warum // else??? Falls das einen Sinn hat, ist diese Variante falsch
        //{
        //    delete this; // wird automatisch ausgeführt
        //}
        ... // <-- und zwar hier
    }
    

    Wenn ich dem noch meinen eigenen Stil aufzwinge, sieht das Ganze so aus:

    class system_data {
      // Reine Daten, alle Pointer smart gemacht, wird automatisch weggeräumt
    }
    
    class system {
    private:
      std::list<system_data> info; // wird automatisch weggeräumt
    }
    

    Du brauchst dann weder delete this noch sonst irgend einen Destruktor.
    Du musst das Übel an der Wurzel packen.



  • übelanderwurzel schrieb:

    Du musst das Übel an der Wurzel packen.

    Designtechnisch kann man über die Notwendigkeit von "delete this" sicherlich
    diskutieren.

    In seinem Fall scheint mir sein "delete this" (, falls er nichts verheimlicht),
    aber als wenig kritisch:
    http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.15



  • Lord_Axiom schrieb:

    Ich habe nun mal gdb verwendet (zum ersten mal), aber viel mehr sagen als das was ich schon wusste tut er ja auch nicht:
    (...)

    Schnapp die eine IDE und Step Zeile für Zeile durch, und guck was passiert (wo genau etwas NULL wird was nicht NULL sein sollte).


Log in to reply