new/delete verständnissproblem
-
Hi Leute,
beschäftige mich gerade mit Speicherreservierung und so.Also versuche es mir am Beispiel eines Arrays klar zu machen, in das man Zahlen eintippt und das irgendwann zu klein wird. Dann wird dynamisch ein neues Array erzeugt (grösser) und alles rüberkopiert. Also ich lerne aus einem Buch und wie es dort drin steht verstehe ich es nicht:
int max = 0; int *pArray = NULL; int *pMore = NULL; int index = 0; bool menu = true; while(menu) { if(index >= max) { cout << "In If-Schleife um zu vergrössern, Array hat gerade " << max << " Elemente" << endl; cin.sync(); cin.get(); pMore = new int[max + 7]; for(int i = 0; i < max; i++) { pMore[i] = pArray[i]; } delete[] pArray; pArray = pMore; max += 7; cout << "und nun " << max << endl; cin.sync(); cin.get(); }ich verstehe Zeile 18 nicht. Dort wird pArray freigegeben obwohl doch mit dem Pointer garnichts reserviert wurde. Ich dachte das darf man nicht. Meine eigene Version davon war, dass ich nach der Übergabe der Adresse von PMore an pArr "delete[] pMore" benutze da ich ja die Adress des neuen Array dort hin gebe. Aber da schmiert alles ab.
Was verstehe ich falsch?
-
Nur mit new angelegter Speicher darf mit delete wieder freigegeben werden.
MfG
-
Weis ich. Der Codeauschnitt ist ja aus dem Buch und funktioniert so auch. Aber warum wird pArr freigegeben (Zeile 18). Ich hab ja in Zeile 13 mit pMore speicher reserviert.
-
pArray zeigt auf den Speicherbereich vom letzten Durchlauf, der zu klein geworden ist. Der wird freigegeben, weil er nicht mehr gebraucht wird.
-
Also kann ich die Adresse des reservierten Speichers auch einem anderen Zeiger zuweisen, und den Speicher muss ich dann auch über den neuen Zeiger Freigeben. Hab ich das richtig verstanden?
Was ist dann aber mit dem alten Zeiger? Zeigt der dann nicht auf Speicher der schon wieder freigegeben wurde?Zu meinem Beispiel: Was ist dann aber mit dem ersten Durchlauf? Bei aufruf von delete ist doch pArray noch NULL.
Und warum ist im 1. durchlauf die Zeile pMore[i] = pArray[i] zulässig?
Mir ist klar das beim ersten mal die for-Schleife garnicht durchlaufen wird. Muss da aber der Compiler nicht meckern weil pArray noch garnicht auf ein Array zeigt?
-
Scripta schrieb:
Also kann ich die Adresse des reservierten Speichers auch einem anderen Zeiger zuweisen,
Ja.
und den Speicher muss ich dann auch über den neuen Zeiger Freigeben.
Wenn mehrere Zeiger auf denselben Speicherbereich zeigen, ist egal, über welchen Zeiger du das freigibst. Hat denselben Effekt.
Was ist dann aber mit dem alten Zeiger? Zeigt der dann nicht auf Speicher der schon wieder freigegeben wurde?
Richtig. Da musst du halt aufpassen.
Zu meinem Beispiel: Was ist dann aber mit dem ersten Durchlauf? Bei aufruf von delete ist doch pArray noch NULL.
Richtig. Macht aber nix. delete NULL tut nichts.
Und warum ist im 1. durchlauf die Zeile pMore[i] = pArray[i] zulässig? Mir ist klar das beim ersten mal die for-Schleife garnicht durchlaufen wird. Muss da aber der Compiler nicht meckern weil pArray noch garnicht auf ein Array zeigt?
Warum sollte er meckern? Und wie überhaupt? Wie soll der Compiler denn zur Compilezeit prüfen, worauf ein Zeiger später zur Laufzeit zeigt? In diesem trivialen Fall mag das noch gehen, aber allgemein geht das nicht.
-
MFK schrieb:
Warum sollte er meckern? Und wie überhaupt? Wie soll der Compiler denn zur Compilezeit prüfen, worauf ein Zeiger später zur Laufzeit zeigt? In diesem trivialen Fall mag das noch gehen, aber allgemein geht das nicht.
Ich meine nur weil ich ja pArray so behandle als ob er auf ein Array zeigt (mit pArray[i]) aber er ist ja noch NULL
-
Scripta schrieb:
Ich meine nur weil ich ja pArray so behandle als ob er auf ein Array zeigt (mit pArray[i]) aber er ist ja noch NULL
Der Zugriff über einen ungültigen Zeiger ist immer ein Laufzeitfehler, ein Problem tritt also erst dann auf, wenn der Code ausgeführt wird. Aber wie du schon gesagt hast, passiert das ja gar nicht, wenn pArray NULL ist.