Dynamischer Speicher, new/delete und RAII
Dynamische Speicherverwaltung beschafft Speicher während der Laufzeit, dessen Lebensdauer nicht direkt an einen einzelnen lokalen Block gebunden sein muss. Ein Besitzer, englisch owner, ist für die Freigabe einer Ressource verantwortlich. Eine Ressource ist etwas, das geordnet freigegeben werden muss, beispielsweise Speicher, eine Datei oder eine Sperre.
Dynamischer Speicher, new/delete und RAII#
Referenzen, Zeiger und Speicher · Lektion 36 von 60
Voraussetzungen: Zeigerfallen. Lernziel: Du verstehst manuelle Speicherverwaltung und warum verwaltende Objekte sie meist ersetzen.
Dynamische Speicherverwaltung beschafft Speicher während der Laufzeit, dessen Lebensdauer nicht direkt an einen einzelnen lokalen Block gebunden sein muss. Ein Besitzer, englisch owner, ist für die Freigabe einer Ressource verantwortlich. Eine Ressource ist etwas, das geordnet freigegeben werden muss, beispielsweise Speicher, eine Datei oder eine Sperre.
Dieses vollständige Beispiel zeigt den Mechanismus bewusst in seiner manuellen Form:
1#include <iostream>2 3int main() {4 int* wert = new int{42};5 std::cout << *wert << '\n';6 delete wert;7 wert = nullptr;8}new int{42} beschafft Speicher und erzeugt darin ein int-Objekt. delete wert zerstört das passende Objekt und gibt den Speicher frei. Der Zeiger selbst ist eine andere, lokale Variable. Gewöhnliches new meldet einen Bereitstellungsfehler durch eine Ausnahme vom Typ std::bad_alloc.
Warum manuelles Aufräumen schwierig wird#
Zwischen new und delete können spätere Änderungen einen frühen Rücksprung oder eine Ausnahme einführen. Dann wird die Freigabe übersprungen und ein Speicherleck entsteht: Belegter Speicher bleibt ohne ordentliche Freigabe verloren.
Bei new T[n] gehört delete[] dazu, bei new T gewöhnliches delete. Mische diese Formen nicht. Speicher für normale lokale Variablen wird nicht mit delete freigegeben. malloc und free aus C haben außerdem keine automatische C++-Objektkonstruktion und sind kein beiläufiger Ersatz.
RAII#
RAII, ausgeschrieben Resource Acquisition Is Initialization, bindet Ressourcen an Objektlebensdauern. Der Besitzer übernimmt die Ressource beim Erzeugen beziehungsweise Initialisieren und gibt sie in seinem Destruktor frei. Verlässt der Code einen normalen Block oder wird er beim Ausnahmeabbau verlassen, laufen die passenden Destruktoren automatisch.
std::vector, std::string, Dateistreams und Smart Pointer setzen dieses Prinzip ein. „Automatisch“ bedeutet nicht, dass ein Hintergrunddienst beliebig später Müll einsammelt. Die Freigabe hängt an einer klaren Objektlebensdauer.
Übung#
Warum ist „an jedem Funktionsende ein delete“ keine robuste Strategie?
Lösung
Eine Funktion kann mehrere Rückwege haben und durch Ausnahmen verlassen werden. RAII koppelt die Freigabe an den Besitzer statt an jede einzeln nachzutragende Kontrollflussstelle.
Weiterlernen#
Zurück: Zeigerfallen: Grenzen, C-Strings und dangling · Kursübersicht · Weiter: unique_ptr, shared_ptr und weak_ptr
Kommentare 0
Kommentare sind für diese Seite deaktiviert.