2009-06-10 13 views
8

mögliche Dubletten:
How does the standard new operator work in c++?
How does delete[] “know” the size of the operand array?Wie löscht [] die Größe eines Arrays?

Dupe von How does delete[] "know" the size of the operand array?

Ich bin gespannt, wie [] aus der Größe des zugewiesenen Speicher Zahlen löschen. Wenn ich so etwas mache:

int* table = new int[5]; 
delete[] table; 

Ich verstehe, dass der Speicher der Tabelle freigegeben wird. Aber was würde passieren, wenn ich den Zeiger einer anderen Tabelle neu zuordnen würde.

int* table = new [5]; 
int* table2 = new [9]; 
table = table2; 
delete[] table; 

Werde ich eine Tabelle der Größe 5 oder 9 freigeben? Ich bin daran interessiert, wie new [] und delete [] Informationen über ihre Größe teilen. Oder vielleicht fehlt mir hier etwas Wesentliches.

+0

Duplizieren (mehr oder weniger) von http://Stackoverflow.com/questions/377178/how-does-the-standard-new-operator-work-in-c/377208 –

+3

Ich stimme nicht zu, das ist genauer. –

+0

Als Randnotiz, und wie in den Antworten erwähnt, ist dies Implementierungsspezifische Sachen. Das bedeutet, dass Sie sich nicht darauf verlassen sollten, wie die Größe des Arrays extrahiert wird, da es sich vom Compiler zum Compiler und von der Compiler-Version zur Compiler-Version ändern könnte. –

Antwort

10

Es würde ein Array der Größe 9 löschen. Es löscht das Array, auf das der Zeiger zeigt.

Es ist nicht angegeben, wie die Größeninformationen gespeichert werden, daher kann jeder Compiler es auf eine andere Weise implementieren, aber eine gängige Methode ist die Zuweisung eines zusätzlichen Blocks vor dem Array. Das heißt, wenn Sie dies tun:

int* table = new int[5]; 

es tatsächlich eine Reihe von sechs ganzen Zahlen ordnet und speichert die Array-Größe in dem ersten Element. Dann gibt es einen Zeiger auf das zweite Element zurück. Um die Größe zu finden, muss delete [] einfach nur Tabelle [-1] lesen.

Das ist ein gängiger Weg, es zu tun, aber der Sprachstandard spezifiziert nicht, dass es auf diese Weise getan werden muss. Nur dass es Arbeit funktioniert.

Ein anderer Ansatz könnte darin bestehen, die Adresse des Arrays als Schlüssel in einer globalen Hash-Tabelle zu verwenden. Jede Methode ist gültig, solange sie die richtigen Ergebnisse liefert.

+0

Danke, diese Erklärung macht mir sehr viel Sinn.Obwohl ich gerne mehrere Antworten als akzeptierte Antwort gewählt hätte. – Lucas

16

Section 16.14 der C++ FAQ Lite Antworten dieses:

Es gibt zwei populäre Techniken, die dies tun . Beide Techniken sind in Verwendung von kommerziellen Compilern, beide Kompromisse haben, und weder ist perfekt. Diese Techniken sind:

* Over-allocate the array and put n just to the left 
    of the first Fred object. 
* Use an associative array with p as the key and n as the value. 
+1

Können Sie einen Compiler mit dem assoziativen Array angeben? – curiousguy

+0

@curiousguy Nach dem Link in der FAQ verwendet CFront dies: http://www.parashift.com/c%2B%2B-faq-lite/compiler-dependencies.html#faq-38.8 –

+0

Sie meinen, der Compiler das hatte nie moderne Vorlagen, das war schon vor 15 Jahren irrelevant, mit [letzte Veröffentlichung im Jahr 1991] (http://www.softwarepreservation.org/projects/c_plus_plus/index.html#cfront): "_Bjarne Stroustrup bemerkt," Eine Warnung dass Cfront 3 vor-standard ist und ausdrücklich nicht für die Verwendung empfohlen wird oder eine weitere Entwicklung möglich ist. "_" – curiousguy

0

Meine Vermutung ist, dass neue [] tatsächlich mehr Daten zuweist, als es scheint. Es hat wahrscheinlich einige Bytes vor dem zurückgegebenen Zeiger, der angibt, wie viele Elemente im Array sind.

4

Wie dies geschieht, ist ein Compiler spezifische Details. Aber der Aufruf zum Löschen von [], der keine Speicherbeschädigung annimmt, löscht immer die richtige Anzahl von Elementen. Es gibt mehrere Möglichkeiten, dies zu erreichen, aber eine einfache Möglichkeit besteht darin, die Länge im Speicher zu verbergen.

Hier ist eine schöne und einfache Möglichkeit, dies zu Demonstrationszwecken zu implementieren. Sagen Sie, Ihr Code ruft new int [10] auf.Anstatt 10 * sizeof (int) zuzuweisen, weist der Compiler (10 * sizefo (int)) + sizeof (size_t) zu. Es gibt dann einen Zeiger auf Sie zurück, der Offset size_t von Anfang an hat. Innerhalb dieses ersten Platzes size_t schreibt er die Zahl 10. Wenn Sie nun delete [] aufrufen und einen Zeiger übergeben, geht der Compiler einfach rückwärts size_t bytes und findet die Anzahl der zu löschenden Elemente.

+0

Argh du schlägst mich dazu - würde genau das gleiche Beispiel posten. – gnud

+0

Das ist ein Beispiel, das es im zugewiesenen Speicher versteckt, nicht "versteckt es im Zeiger". –

+0

@Dan, yep den Tippfehler behoben – JaredPar

1

Der Mechanismus ist implementierungsabhängig, wird aber nicht "getäuscht", wenn Sie den Zeiger in Ihrem Beispiel neu zuweisen. Es wird das Array der Größe 9 freigeben, genau wie du es ihm gesagt hast (und in diesem Fall wird es einen Speicherverlust geben, da das Array der Größe 5 jetzt nichts mehr darauf hinweist).

2

Wie delete [] funktioniert, ist implementierungsabhängig, aber der globale neue Operator ordnet einen Deskriptor dem zugewiesenen Speicher in irgendeiner Weise zu (in den meisten Fällen wird er dem zugewiesenen Speicher vorangestellt oder in einer Nachschlagetabelle gespeichert). Der Deskriptor enthält die tatsächliche Größe des Speichers, der zugewiesen wurde.

In Ihrem zweiten Codebeispiel löscht delete [] das neun Elemente umfassende Array von int, und das ursprüngliche Array mit fünf Elementen wird durchgesickert.

0

Sie, dass der Systemspeicher in einer Struktur wie dies die Größe der Tabelle vorstellen konnte:

struct MemoryAllocated 
    { 
    size_t sizeOfMemory; 
    char* yourData; 
    } 

jeder Ihre einige Zuweisen von Speicher geben, kehrt das System einen Zeiger auf ‚yourData‘. Und jeder Typ Ihr ​​Speicher ist "frei", das System verschiebt den Zeiger, um die "sizeOfMemory" zu bekommen. Siehe auch std :: allocator

0

im neuen Fall []/delete [], was geschieht memory-weise ist gleich/ähnlich zu dem, was passiert in new/delete case ... die Größe info wird in der (größer) Block selbst zugewiesen. Was für Arrays interessant ist, ist, dass es auch die Größeninformationen verwendet, um zu wissen, wie viele Objekte Destruktoren aufgerufen werden sollen.

Verwandte Themen