new & delete



  • hi,
    delete ist für mich ein mysterium!

    class CTest
    {
    public:
    	CTest(){cout<<"constructor CTEST"<<endl;};
    	~CTest(){cout<<"Destructor CTEST "<<endl;};
    	void SagHallo(){cout<<"CTest::Hallo()"<<endl;};
    };
    
    int main(void)
    {
    
    	CTest* pTest = new CTest;
    	pTest->SagHallo();
    
    	delete pTest;
    	pTest->SagHallo();
    
    	system("pause");
    	return 1;
    }
    

    der befehl

    pTest->SagHallo();
    

    wird trotzdem ich vorher den delete aufgerufen habe ausgefuehrt.
    warum?



  • Weil nirgends steht dass das Programm dort abstürzen muss oder sonst etwas. Das Verhalten bei Zugriff auf freigegebenen Speicher ist _undefiniert_, das heisst es kann so gut wie alles passieren.



  • der pointer zeigt trotzdem noch auf denselben speicherbereich. solange da nix überschrieben wird, liegt immer noch das objekt im speicher. allerdings ist der speicherbereich zum überschreiben freigegeben.



  • Hi!

    Ja, bei Theresa mag das so ablaufen. Aber davon ausgehen darf man auf keinen Fall, denn das Verhalten ist, wie gesagt, undefiniert und kann auch zu Abstürzten etc... führen.

    grüße



  • Theresa schrieb:

    der befehl

    pTest->SagHallo();
    

    wird trotzdem ich vorher den delete aufgerufen habe ausgefuehrt.
    warum?

    Solange die Funktion CTest::SagHallo() kein this verwendet, sollte das auch keine Probleme machen, da der (nicht mehr gültige) Speicher des Objektes gar nicht verwendet wird (gilt nicht für virtuelle Methoden).



  • und da die funktion nicht static ist wird sie wohl einen this zeiger haben...



  • Solange dieser nicht verwendet wird macht das aber nichts.
    Ich sagte, dass die Funktion keinen this-Zeiger verwendet. Natürlich hat sich als nicht-statische Methode einen.



  • und du meinst, der this zeiger zeigt (auch wenn er nicht "benutzt" wird) einfach irgendwo hin?

    dann dürfte es ja auch keine probleme geben, wenn der freigegebene speicher überschrieben wird, und die funktion aufgerufen wird....hm...oder???



  • Es ist irrelevant wo ein Zeiger hinzeigt, wenn er nicht benutzt wird. Der Aufruf macht somit keine Probleme.



  • Neku schrieb:

    Es ist irrelevant wo ein Zeiger hinzeigt, wenn er nicht benutzt wird. Der Aufruf macht somit keine Probleme.

    Laut Standard ist das Verhalten hier undefiniert. Es ist ja schön für dich, wenn du einen Compiler benutzt, der hier etwas definiertes tut, aber daraus solltest du (zumindest in diesem Unterforum) keine allgemeingültigen Ratschläge ableiten.



  • Neku schrieb:

    Es ist irrelevant wo ein Zeiger hinzeigt, wenn er nicht benutzt wird. Der Aufruf macht somit keine Probleme.

    ich bitte dich, wenn du einen nichtstandard compiler hast, der vielleicht auch möhren ordentlich umsetzt, hier keine falschen ratschläge zu geben!

    das verhalten hier ist undefiniert, und man sollte anfängern nie sagen, das es egal ist wo ein zeiger hinzeigt, solang er nicht benutzt wird!

    es ist nie egal wo ein zeiger hinzeigt!

    [Edit] zu spät



  • Laut Standard ist das was dort gemacht wird IMHO undefiniert, völlig egal was ein einzelner C++-Compiler da verwendet oder nicht verwendet.

    [Edit] Auch zu spät



  • int* p = (int*)2;
    

    Wieso sollte das ein Problem darstellen, wenn 'p' nicht genutzt wird?



  • p->tuWas();
    

    Hier wird p benutzt (_Egal_ was in tuWas passiert! Darum gehts im Übrigen auch bei Kapselung - nicht wissen zu müssen was tuWas tut.)



  • Neku schrieb:

    int* p = (int*)2;
    

    Wieso sollte das ein Problem darstellen, wenn 'p' nicht genutzt wird?

    es ging grad um den this zeiger?
    andere frage, wieso baust du die nen zeiger, lässt den irgendwo hinzeigen, wenn du den NIE benutzt?

    was willst du vermitteln?



  • Hat jemand einen Link zum C++ Standard? Hatte ich bisher noch nie benötigt, da ich weder bei VC++ noch bei g++ Probleme hatte bisher.



  • Neku schrieb:

    Hat jemand einen Link zum C++ Standard?

    Du kannst den C++ Standard für 30$ käuflich erwerben:
    http://webstore.ansi.org/ansidocstore/product.asp?sku=INCITS%2FISO%2FIEC+14882-2003

    Alternativ kannst du auch in den Final Draft schauen, den gibt es kostenlos:
    http://www.kuzbass.ru:8086/docs/isocpp/



  • Danke, habe bisher aber keine Informationen zu dem Problem gefunden.
    Dann schränke ich die Aussagen erstmal auf VC++ und g++ ein ^^



  • Ich kann noch mehr Verwirrung stiften:

    #include <iostream>
    using namespace std;
    
    class CTest 
     { 
     public: 
         CTest(){cout<<"constructor CTEST"<<endl;}; 
         ~CTest(){cout<<"Destructor CTEST "<<endl;}; 
         void SagHallo(){cout<<"CTest::Hallo()"<<endl;}; 
     };
     int main(int argc, char* argv[]) 
     { 
    
         CTest* pTest = 0; 
         pTest->SagHallo(); 
         return 1; 
     }
    

    geht auch 🙂
    Sollte man natürlich nicht tun, aber es gibt tatsächlich keinen Grund, warum es nicht gehen sollte. Allerdings geht das schon nicht, wenn die Methode virtuell ist. Aber so...

    Tommi



  • tntnet schrieb:

    [...] aber es gibt tatsächlich keinen Grund, warum es nicht gehen sollte.

    Doch siehe oben: Das Verhalten ist undefiniert. 👎



  • Man möge sich die folgenden Stellen im Standard anschauen:
    3.8. Object lifetime. Besonders 3.8/5
    9.3.1
    5.2.5/1-4

    Danach sollte einem klar sein, warum alle hier gezeigten Beispiele zu undefiniertem Verhalten führen.

    Mir ist allerdings nicht klar, warum man dazu erst in den Standard schauen muss. Es reicht eigentlich doch der gesunde Menschenverstand um verstehen zu können, dass hier Leichenfledderei betrieben wird. Und die ist in keiner Kultur gern gesehen.


Anmelden zum Antworten