New und delete



  • Hallo zusammen,

    mit folgendem Beispiel bekomme ich beim Deleten von "i" eine Zugriffsverletzung (BDS2006):

    void __fastcall TForm1::Button5Click(TObject *Sender)
    {
     int k, test;
     int *iArray = new int[10];  
     int *i = new int(66); // Mit 66 initialisieren
    
     test      = 4711;     // Werte zuweisen
     iArray[0] = 99;
     iArray[1] = 100;
    
     i         = &test;
     k         = *i;
    
     delete i;             // Hier knallts
     delete[] iArray;
    }
    //---------------------------------------------------------------------------
    
    Erste Gelegenheit für Exception bei $7C812A5B. Exception-Klasse EAccessViolation mit Meldung 'Zugriffsverletzung bei Adresse 2115470D in Modul 'BORLNDMM.DLL'. Schreiben von Adresse 00000063'. Prozess Zeiger.exe (3536)
    

    Ich habe keine Idee was hier falsch sein könnte.



  • Hallo

    int test; // normale Stackvariable
    int *i = new int(66); // Zeiger mit dynamisch reserviertem Speicher auf dem Heap
    i         = &test; // Zeiger wird umgelegt auf die Adresse der Stackvariable. 
    // Der dynamisch angeforderte Speicherbereich auf dem Heap ist nun nicht mehr erreichbar
    delete i;             // Anwendung des delete-Operators auf den Speicherbereich hinter dem Zeiger. 
    // Da aber zur Zeit der Zeiger auf eine Stackvariable zeigt, ist die Operation nicht gültig.
    

    Eventuell wolltest du so etwas schreiben?

    int test; // normale Stackvariable
    int *i = new int(66); // Zeiger mit dynamisch reserviertem Speicher auf dem Heap
    *i         = test; // Der Wert von test wird in den Speicherbereich hinter dem Zeiger i kopiert.
    delete i;             // Löschen des Speicherbereiches hinter i
    

    bis bald
    akari



  • void __fastcall TForm1::Button5Click(TObject *Sender)
    {
     int k, test;
     int *iArray = new int[10];  
     int *i = new int(66); // Mit 66 initialisieren <--- () geht nicht !! wird nicht mit 66 initialisiert sondern du erzeugst ein arry aus zeigern
    
     test      = 4711;     // Werte zuweisen
     iArray[0] = 99;
     iArray[1] = 100;
    
     i         = &test; <-- geht auch nicht !! du setzt zeiger auf zeiger -> falsch
     k         = *i;
    
     delete i;             // Hier knallts <-- weil du (66) gemacht hast
     delete[] iArray;
    }
    //---------------------------------------------------------------------------
    

    Lese nochmal ein Zeiger Tutorial durch!



  • Hallo

    Ich muß Maverick widersprechen und ihm selber nochmal ein Tutorial empfehlen.

    Maverick schrieb:

    int *i = new int(66); // Mit 66 initialisieren <--- () geht nicht !! wird 
    nicht mit 66 initialisiert sondern du erzeugst ein arry aus zeigern
    

    Selbstverständlich geht das. Auch int hat einen Konstruktor, mit dem man gleich einen Initialisierungswert mitgeben kann. () und [] sind zwei verschiedene Sachen.

    Maverick schrieb:

    i         = &test; <-- geht auch nicht !! du setzt zeiger auf zeiger -> falsch
    

    Selbstverständlich geht das. Auch Zeiger sind normale Variblen und lassen sind zuweisen. Da wird dann eben die Adresse des Zeigers kopiert. Syntaktisch ist das in Ordnung, nur über die Konsequenzen muß man sich im klaren sein.

    Maverick schrieb:

    delete i;             // Hier knallts <-- weil du (66) gemacht hast
    

    Es knallt nicht wegen der 66, sondern wegen der von mir bereits verdeutlichen Speicherzuordnung.

    bis bald
    akari



  • Hallo akari,

    vielen Dank für Deine ausführliche Beschreibung. Eine Frage habe ich noch:

    akari schrieb:

    Maverick schrieb:

    i         = &test; <-- geht auch nicht !! du setzt zeiger auf zeiger -> falsch
    

    Selbstverständlich geht das. Auch Zeiger sind normale Variblen und lassen sind zuweisen. Da wird dann eben die Adresse des Zeigers kopiert. Syntaktisch ist das in Ordnung, nur über die Konsequenzen muß man sich im klaren sein.
    akari

    Hier habe ich doch keinen Zeiger auf Zeiger, sondern nur dem Zeiger "i" die Adresse von test zugewiesen, oder verstehe ich da noch was falsch ?



  • Hallo

    Aus &test wird vom Datentyp her auch ein (temporärer) Zeiger. Der Zuweisungsoperator sieht also rechts nur einen Zeiger.

    bis bald
    akari



  • akari schrieb:

    Maverick schrieb:

    int *i = new int(66); // Mit 66 initialisieren <--- () geht nicht !! wird 
    nicht mit 66 initialisiert sondern du erzeugst ein arry aus zeigern
    

    Selbstverständlich geht das. Auch int hat einen Konstruktor, mit dem man gleich einen Initialisierungswert mitgeben kann. () und [] sind zwei verschiedene Sachen.

    Interessant, wusste ich garnicht. Stand zumindest in meinem Buch nix darüber - oder ich habs überlesen (also das mit new ()). Also ich pers. habs bisher immer mit Brackets gemacht.

    akari schrieb:

    Selbstverständlich geht das. Auch Zeiger sind normale Variblen und lassen sind zuweisen. Da wird dann eben die Adresse des Zeigers kopiert. Syntaktisch ist das in Ordnung, nur über die Konsequenzen muß man sich im klaren sein.

    Das Zeiger normale Variablen sind weiss ich auch.

    akari schrieb:

    Hallo

    Aus &test wird vom Datentyp her auch ein (temporärer) Zeiger. Der Zuweisungsoperator sieht also rechts nur einen Zeiger.

    bis bald
    akari

    Warum? Er hat die Variable doch bereits als Zeiger definiert? Ob man jetzt int bla[wert]; oder int *bla = new int[wert] macht ist doch das gleiche? Das Resultat ist das gleiche -> array aus zeigern...? Also so hab ICH es zumindest verstanden...



  • Hallo

    Er hat die Variable doch bereits als Zeiger definiert?

    test ist kein Zeiger, und nur um diese Variable ging es mir bei dem Term &test. Denn der Compiler fängt beim Auswerten auch immer rechts des Zuweisungsoperators an.

    Ob man jetzt int bla[wert]; oder int *bla = new int[wert] macht ist doch das gleiche? Das Resultat ist das gleiche -> array aus zeigern...? Also so hab ICH es zumindest verstanden...

    Es ist nicht daselbe.
    int[] ist ein statisches Array mit zur Laufzeit fester Größe. Alle Elemente liegen auf dem Stack.
    *int bla = new int[wert] ist ein Zeiger auf ein dynamisch reserviertes Array auf dem Heap. Der Zeiger selber liegt auf dem Stack, die Elemente aber liegen auf dem Heap.

    Der Unterschied macht sich auch in der Syntax bemerkbar. Zwar lassen sich auf beide der []-Op anwenden. Aber nur auf den Zeiger läßt sich die Zeigerarithmetik anwenden.

    bis bald
    akari


Anmelden zum Antworten