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.
akariHier 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
akariWarum? 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