2012-03-25 12 views
1

Wenn ich new [] verwenden, um Speicher anzuwenden. Am Ende verwende ich delete, um Speicher freizugeben (nicht delete[]). Wird dies Speicherverlust verursachen?Wie werden delete und delete [] implementiert?

Zwei Typen:

  1. Builtin Typen, wie int, char, double ...
    Ich bin nicht sicher.
  2. Klassentypen.

Ich denke, kann frei Leck. weil die Zerstörungsfunktion.

Viele Leute und einige Bücher sagen mir, new[] ->delete[]; new ->delete.
Ich möchte wissen, warum. so überprüfe ich vs2010 Quellcode, es muss Speicherpool Mechanismus verwendet werden. Es ist lang und komplex. Ich kann nicht weiter lesen.

Wie werden delete und delete[] implementiert?

Antwort

4

Wenn ich neu [] verwende, um Speicher anzuwenden. Am Ende benutze ich delete, um Memeory zu löschen (nicht delete []). Muss Speicherleck sein?

Wenn Sie new[] verwenden, und dann delete (nicht delete[]), dann nach dem Langauge Spezifikation, ruft sie undefiniert-Verhalten, das etwas bedeutet passieren könnte. Es kann Speicherverlust verursachen oder nicht. Eine solche Garantie gibt weder die Sprache noch der Ersteller.

Viele Leute und einige Bücher sagen mir, neu [] -> löschen []; neu-> löschen Ich möchte wissen warum?

Kurze Antwort: weil die Spezifikation so sagt.

Lange Antwort: Die Funktionen, die new und new[] implementieren sind unterschiedlich umgesetzt: new übernimmt Erinnerung an ein Element zugeordnet werden soll, während new[] übernimmt Erinnerung an n Artikel ist zugeteilt werden, wo n der Funktion als Argument übergeben wird. Um den Prozess rückgängig zu machen (d. H. Den Speicher freizugeben), sollten auch zwei Funktionen vorhanden sein: delete und delete[], die unterschiedlich implementiert sind, wobei jede eine gewisse Annahme über den von ihren Gegenstücken zugewiesenen Speicher macht. Zum Beispiel nimmt delete einfach an, dass Speicher, der für ein Element zugewiesen ist, freigegeben werden soll; Andererseits muss delete[] die Anzahl der Elemente kennen, für die der Speicher freigegeben werden soll. Daher wird angenommen, dass new[] die Nummer der Elemente irgendwo im zugewiesenen Speicher speichert, am häufigsten im Anfang des zugewiesenen Speichers und so delete[] liest zuerst den Teil des Speichers, der die Anzahl der Elemente speichert, und hebt dann die Zuordnung des Speichers entsprechend auf.

anzumerken, dass new und new[] die jeweils den Standard-Konstruktor ruft das Objekt (e) in dem zugewiesenen Speicher und deletedelete[] und ruft den Destruktor zu zerstören das Objekt vor dem Aufheben der Zuordnung des Speichers zu konstruieren.

+0

obwohl wahr, es ist nicht die Frage [ich * denke *] - er fragt nach, wie es umgesetzt wird [ich stimme zu, die Frage war nicht sehr klar, bevor ich es editierte ...] – amit

+0

Zuerst, danke. Amit, ist richtig. Ich möchte wissen, "wie ist es umgesetzt?" –

+0

@chinazhangjie: Ich denke, ich habe * in Kürze * erläutert, wie jeder implementiert ist. Sie möchten eine * aktuelle * Implementierung? – Nawaz

0

Sie sollten dies nicht tun. Für die meisten Implementierungen können Sie jedoch ein Array mit delete löschen, anstatt delete [], , solange der Elementtyp des Arrays keinen Destruktor hat.

Bei einem Typ mit Destruktor muss new [] die Länge des Arrays irgendwo im dynamisch zugewiesenen Speicherblock aufzeichnen. delete [] zerstört jede Element-Basis und gibt den Speicher frei. Und löschen wird eine solche Struktur nicht erkennen. Vielleicht ist es Speicherleck, vielleicht wirst du eine Ausnahme bekommen.

4

Es ist kein Speicherleck; Es ist undefined Verhalten. Das ist viel schlimmer.

Der Aufruf von delete an Speicher, der von new[] zugewiesen wurde, kann dazu führen, dass der Heap beschädigt wird, was Ihre Anwendung zum Absturz bringen kann. Natürlich nicht sofort, denn das wäre zu nützlich. Es wird irgendwann später abstürzen, lange nachdem der Heap beschädigt wurde, um es fast unmöglich zu machen, aufzuspüren.

Verwenden Sie immer delete[] mit new[]. Eigentlich nie mit new[] beginnen. Verwenden Sie eine std::vector, es sei denn, Sie haben sehr spezielle und spezifische Bedürfnisse.

Ich möchte wissen, warum?

Warum ist das wichtig? Es ist falsch und führt zu einem defekten Programm. Es ist falsch, weil der C++ - Standard dies sagt.

Wenn Sie jedoch auf Grund bestehen ...

Beachten Sie, dass Sie eine beliebige Anzahl von Elementen mit new[] zuordnen kann. Sie können dort eine beliebige Zählnummer (aka: positive ganze Zahl) eingeben. So können Sie new int[50] oder new int[someIntegerVariable] haben. Es ist alles gut.

Beachten Sie auch, dass delete[] tut nicht eine Zählung nehmen. Nun ... wie ist das möglich? Wenn Sie 50 int s zuweisen, muss natürlich delete wissen, wie viele Sie zugewiesen haben, richtig? Aber du musst es nicht sagen; es weiß automatisch.

Wie? Weil new int[50]mehr zuweist als nur ein Array von 50 int s. Es weist auch genügend Speicherplatz zu, um die Größe der Zuweisung zu halten. Stellen Sie sich vor, Sie würden 51 int s zuweisen, aber nur 50 von ihnen verwenden.

Dann kommt delete[] kommt daher. Es ermittelt, wo die Zählung zu finden ist, die new[] zugeordnet ist. Und es verwendet diese Zählung, um den Speicher freizugeben.

delete tut nicht dies tun. Daher kann nicht korrekt den Speicher freigeben.

1

Nawaz ist richtig, dass es "weil die Spezifikation so sagt".

Der Implementierungsgrund dahinter ist, dass der Compiler, wenn Sie delete aufrufen, einen Aufruf an den Destruktor des Objekts vor dem Freigeben des Speichers hinzufügt.

Bei einem Array hängt die Anzahl der Aufrufe von Destruktoren von der Anzahl der zugeordneten Objekte ab, die nur zur Laufzeit bekannt sind. So new[] speichert zusätzliche Informationen hinsichtlich der Anzahl der Objekte, die delete[] verwendet.

Diese Information wird nicht benötigt, wenn new/delete verwendet wird.