2008-10-13 14 views
174
Foo* set = new Foo[100]; 
// ... 
delete [] set; 

Sie übergeben die Grenzen des Arrays nicht an delete[]. Aber wo ist diese Information gespeichert? Ist es standardisiert?Wie löscht [] die Größe des Operandenarrays?

+0

http://sourceforge.net/projects/fastmm/ ist Open Source und ersetzt den Speicher-Manager. Hier erfahren Sie, wie die Speicherverwaltung funktioniert und woher die Informationen stammen, um Speicher zuzuordnen und zu löschen. –

+0

Beachten Sie, dass FastMM nur für die Delphi/C++ Builder-Compiler spezifisch ist. Es ist kein allgemeiner Speichermanager für C++. Es ist nicht einmal in C++ geschrieben. –

Antwort

121

Wenn Sie Speicher auf dem Heap reservieren, wird Ihr Zuordner verfolgen, wie viel Speicher Sie zugeordnet haben. Dies wird normalerweise in einem "Kopf" -Segment kurz vor dem Speicher gespeichert, den Sie zugewiesen bekommen. Wenn der Speicher freigegeben wird, weiß der De-Allocator genau, wie viel Speicher frei ist.

+2

Beachten Sie, dass dies nur für Arrayzuordnungen in C++ gilt. Alle anderen Zuweisungen hängen von der Größe des Typs ab. Einige Bibliotheken speichern alle Zuweisungsgrößen, normalerweise nur im Debugging-Modus. –

+72

Es gibt absolut keinen Grund, warum diese Information nicht für den Programmierer verfügbar sein sollte. Ich kann einen Zeiger auf eine Funktion übergeben und freigeben, aber um die Größe selbst zu erhalten, muss ich einen zusätzlichen Parameter übergeben. Macht das irgendeinen Sinn? –

+21

@Mark, es macht eine * kleine * Menge an Sinn, weil in der Theorie es den Zuordner freigibt, um immer die Größe des * zugewiesenen * Blocks zu speichern (die von der Größe des * angeforderten * Blocks abweichen kann). Bestimmte Zuweiserdesigns benötigen diese Informationen möglicherweise für ihre eigenen Zwecke oder sind möglicherweise nicht ausgefeilt genug, um Typinformationen zu verwenden, um die Größe von Nicht-Array-Heapzuweisungen usw. zu verfolgen. Der Zuordner wird gezwungen, die angeforderte Größe zu speichern müssen die Array-Größe selbst übergeben) könnte eine kleine Belastung sein, aber es könnte Auswirkungen auf die Auswirkungen auf denkbare Allocator Designs haben. –

3

Dies ist nicht etwas, das in der Spezifikation ist - es ist abhängig von der Implementierung.

2

Da das zu löschende Array mit einer einzigen Verwendung des Operators 'new' erstellt werden sollte. Die 'neue' Operation hätte diese Information auf den Heap legen sollen. Ansonsten, wie würde zusätzliche Verwendung von neuen wissen, wo der Haufen endet?

0

Es ist nicht standardisiert. In der Laufzeit von Microsoft verwendet der neue Operator malloc() und der Löschoperator verwendet free(). In dieser Einstellung entspricht Ihre Frage also der folgenden: Wie kann free() die Größe des Blocks erkennen?

Es gibt einige Buchhaltung hinter den Kulissen, d. H. In der C-Laufzeit.

+4

Nicht wahr. Vor dem Aufruf von free muss delete [] Destruktoren zuerst aufrufen. Für diese wissende Allokationsgröße ist nicht genug. Tatsächlich funktioniert new [] und delete [] für einfache und zerstörte Typen in VC++. – Suma

7

Die Informationen sind nicht standardisiert. In den Plattformen, an denen ich gearbeitet habe, werden diese Informationen jedoch kurz vor dem ersten Element gespeichert. Man könnte also theoretisch darauf zugreifen und es inspizieren, aber es lohnt sich nicht.

Aus diesem Grund müssen Sie delete [] verwenden, wenn Sie Speicher mit new [] zugewiesen haben, da die Array-Version von delete weiß, dass (und wo) es die richtige Menge an Speicher freigibt - und ruft die entsprechende Anzahl von Destruktoren für die Objekte.

2

Es ist im C++ - Standard als compilerspezifisch definiert. Was Compilermagie bedeutet. Es kann mit nicht-trivialen Ausrichtungsbeschränkungen auf mindestens einer Hauptplattform brechen.

Sie können über mögliche Implementierungen denken, indem zu realisieren, dass delete[] nur für Zeiger von new[] zurück definiert ist, die nicht der gleiche Zeiger von operator new[] wie zurückgegeben werden. Eine Implementation in der Wildnis besteht darin, die Array-Zählung im ersten int zu speichern, der von operator new[] zurückgegeben wird, und new[] gibt einen Zeigeroffset zurück, der über diesen Wert hinausgeht. (Deshalb können nicht-triviale Ausrichtungen new[] brechen.)

Beachten Sie, dass operator new[]/operator delete[]! = new[]/delete[].

Plus, das ist orthogonal zu, wie C die Größe des Speichers weiß, der von malloc zugeteilt wird.

4

Grundsätzlich im Speicher seiner angeordnet sind, wie:

[info] [mem Sie gefragt ...]

Wo info die Struktur durch den Compiler zu speichern, die Menge an Speicher zugewiesen, verwendet wird, und dem, was nicht.

Dies ist jedoch implementierungsabhängig.

10

Einer der Ansätze für Compiler ist es, ein wenig mehr Speicher zuzuordnen und eine Anzahl von Elementen in einem Kopfelement zu speichern.

Beispiel, wie es gemacht werden könnte:

Hier

int* i = new int[4]; 

Compiler sizeof(int)*5 Bytes zuteilen wird.

int *temp = malloc(sizeof(int)*5) 

speichert "4" in dem ersten Byte sizeof(int)

*temp = 4; 

und stellen i

i = temp + 1; 

i So werden die Punkte auf ein Array von Elementen 4, 5 nicht

Und Löschen

delete[] i; 

wird auf folgende Weise verarbeitet:

int *temp = i - 1; 
int numbers_of_element = *temp; // = 4 
... call destructor for numbers_of_element elements 
... that are stored in temp + 1, temp + 2, ... temp + 4 if needed 
free (temp) 
0

Dies ist ein interessantes Problem, als man zunächst denken könnte. Diese Antwort bezieht sich auf eine mögliche Implementierung.

Erstens, während auf einer gewissen Ebene Ihr System muss wissen, wie man 'frei' der Speicherblock, der zugrunde liegende malloc/free (die neue/löschen/new []/delete [] rufen im Allgemeinen) nicht immer daran denken, Genau wie viel Speicher Sie benötigen, es kann aufgerundet werden (wenn Sie zum Beispiel über 4K sind, wird es oft auf den nächsten 4K-Block aufgerundet).

Daher, auch wenn die Größe des Speicherblocks erhalten könnte, sagt uns das nicht, wie viele Werte im neuen Speicher vorhanden sind, da es kleiner sein kann. Daher müssen wir eine extra Ganzzahl speichern, die uns sagt, wie viele Werte es gibt.

AUSSER, wenn der Typ, der erstellt wird, keinen Destruktor hat, dann muss delete [] nichts anderes tun, als den Speicherblock freizugeben und muss daher nichts speichern!

Verwandte Themen