PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C++: woher weiß delete...


Imperator Katarn
2005-11-11, 12:30:46
... wieviel Speicher es freizugeben hat?

Beispiel:

double *pData = new double[666];
// ...
delete [] pData;

wo kommt in der delete-Zeile die Information her, daß der freizugebende Speicherbereich die Größe 666*sizeof(double) hat?
Ein Kollege meinte, beim Allozieren des Speichers werde zugleich ein Overhead-Speicherbereich angelegt, in dem solche Informationen gespeichert werden, die dann von delete abgerufen werden. Stimmt das?

Edit: Tippfehler behoben.

Ganon
2005-11-11, 12:37:44
Afaik musst du bei Zeigern auf ein Array
delete[] pData
benutzen anstatt delete.

Beantwortet zwar die Frage nicht aber sollte man, denke ich, erwähnen. ;)

Coda
2005-11-11, 12:42:53
Der Code ist falsch. Es muss delete[] heißen. Bei POD-Typen macht das meistens nicht (es ist trotzdem undefined behaviour), aber bei Klassen wird dann nur der erste Destruktor aufgerufen.

Ein Kollege meinte, beim Allozieren des Speichers werde zugleich ein Overhead-Speicherbereich angelegt, in dem solche Informationen gespeichert werden, die dann von delete abgerufen werden. Stimmt das?Ja. Wie genau das sich verhält ist aber Runtime- und OS-spezifisch.

gereggter Gast
2005-11-11, 16:10:45
wo kommt in der delete-Zeile die Information her, daß der freizugebende Speicherbereich die Größe 666*sizeof(double) hat?
Ein Kollege meinte, beim Allozieren des Speichers werde zugleich ein Overhead-Speicherbereich angelegt, in dem solche Informationen gespeichert werden, die dann von delete abgerufen werden. Stimmt das?

Edit: Tippfehler behoben.Ja, es werden noch zusätzliche Informationen dem Array bzgl. gespeichert, wozu natürlich auch die Länge des Arrays gehört. Nicht umsonst gibt es auch in C++ einen Befehl (glaube get_Length), die die Länge des Arrays zurückgibt. Für den Fall eines mehrdimensionalen Arrays werden entsprechend auch die anderen Längen gemerkt.

Coda
2005-11-11, 16:53:42
Nicht umsonst gibt es auch in C++ einen Befehl (glaube get_Length), die die Länge des Arrays zurückgibt.Nein. So etwas gibt es nicht. Man kann die Länge eines dynamisch allozierten Arrays nicht abfragen.

Imperator Katarn
2005-11-11, 17:14:26
Nein. So etwas gibt es nicht. Man kann die Länge eines dynamisch allozierten Arrays nicht abfragen.warum eigentlich nicht? Wenn delete es kann? Und warum werden solche Zusatzinformationen nur bei dynamisch erzeugten Arrays angelegt?

del_4901
2005-11-11, 20:57:32
warum eigentlich nicht? Wenn delete es kann? Und warum werden solche Zusatzinformationen nur bei dynamisch erzeugten Arrays angelegt?

weil delete eine systemfunktion aufruft, welche zugriff auf den kompletten Speicher hat. Ein Programm kann selbst nicht aus seinem Virtuellen Adressraum raus.

zeckensack
2005-11-12, 17:07:45
weil delete eine systemfunktion aufruft, welche zugriff auf den kompletten Speicher hat. Ein Programm kann selbst nicht aus seinem Virtuellen Adressraum raus.Richtig, bis auf das fett markierte :|
Nicht deswegen.

Die Info über Speicherblöcke im Applikationsheap liegen schon im direkten Zugriff, nur kommt man da ohne Wissen um die Interna der Runtime nicht dran. Selbst wenn man es rauskriegt, portabel ist es nie und nimmer.

@Topic,
new X[n] und delete[] könnten zB so implementiert sein:
template <class T> T* operator new[](int size)
{
size_t* allocation=(size_t*)malloc(sizeof(size_t)+size*sizeof(T));
*allocation=size; //größe des Arrays im allozierten Speicher parken
T* rv=(T*)(allocation+1); //den Rest des Speichers zurückgeben
//Konstruktoren aufrufen
for (int n=0;n<size;++n) (rv+n)->T::T(); //oder wie auch immer das korrekt wäre ...
return(rv);
}

template <class T> void delete[](T* p) //kompiliert wohl garnicht ... aber egal
{
size_t* magic=(size_t*)p;
//Array-Größe aus dem "Versteck" wiederholen
size_t array_size=magic[-1];
//Destruktoren aufrufen
for (int n=0;n<array_size;++n) (p+n)->~T();

free(magic);
}

Ich glaube kaum dass das so kompiliert, aber ich denke die Idee ist klar. Die Größe des Arrays wird einfach eine bekannte Anzahl Bytes vor dem Beginn desselben gespeichert. Dazu benötigt man ein paar Bytes mehr als das Array alleine bräuchte, ist aber kein Problem, kann man sich holen. Diese Extra-Bytes am Anfang "versteckt" man dann vor dem Kunden, indem man ihm einfach keinen Zeiger darauf gibt. Braucht man auch nicht, denn man kann den Zeiger auf diese Bonus-Information trivial aus dem Basiszeiger (dh der Zeiger, der auf den echten Anfang des Arrays zeigt) herleiten.

Eine echte Implementierung würde sich dann noch um gesundes Alignment der Instanzen kümmern. Und so.

Demirug
2005-11-12, 17:40:32
Wer sich für sowas interssiert kann sich ja mal den Heapmanager eines beliebigen Compilers anschauen bei dem der Quellcode der Runtime mitgeliefert wird.

Der vom VC++ ist recht interesant weil er in der Debugversion auch noch gleich eine Speicherleck Überwachung hat.