zurück weiter

C++ - Stack, Speicherallokation

G.Eichelsdörfer
Staatliche Technikerschule Weilburg

Ein Programm wird zwecks Ausführung in den Arbeitsspeicher geladen und erhält wenigstens teilweise einen Prozessor, der das Programm ausführt. So wird ein Programm zu einem Prozess. Ein Prozess erhält vor seiner Ausführung zusätzlichen Arbeitsspeicher zugeteilt. Dieser zusätzliche Speicher liegt im Adressraum oberhalb des Programmcodes.

Wenn viele Daten zwecks Verarbeitung im Arbeitsspeicher abgelegt werden müssen, dann verwendet man Datenfelder oder einen Container der Standardbibliothek - Container betrachten wir später. Wenn ein solches Datenfeld als lokale Variable angelegt wird, wird dafür der Stack verwendet. Die Kapazität (Größe) eines solchen Datenfeldes muss zur Übersetzungszeit feststehen, weil der Compiler dafür Code erzeugen muss. Liegt diese Kapazität erst zur Laufzeit fest, muss zur Laufzeit dafür Speicher im "free store" reserviert werden. Man nennt diesen Vorgang Speicherallokation - Speicher wird allokiert (manche Autoren schreiben "alloziert"). Ein per Allokation angelegtes Datenfeld nennt man auch ein dynamisches Datenfeld.

Allokieren von Speicher

Dafür gibt es den Operator new. Dieser sorgt für die Speicherallokation und liefert die Anfangsadresse des allokierten Speichers, welche einer geeigneten Zeigervariablen zuzuweisen ist. Mit Hilfe des Zeigers kann man auf den allokierten Speicher zugreifen.
Beispiel:
Angenommen wir brauchen Speicherplatz für ein Datenfeld aus 1000 double-Werten.
double *DP;
DP = new double[1000];

oder kurz
double *DP = new double[1000];
Nun können wir mit Hilfe des Zeigers DP auf den allokierten Speicher zugreifen - entweder unter Verwendung eines Index (DP[i]) oder mit Hilfe der Zeigerarithmetik (*(DP+i)).
Beispiel zur Addition aller 1000 Werte im inzwischen gefüllten dynamischen Datenfeld:
double *P, Summe = 0;
for (P=DP;P!=DP+1000;++P)
 Summe += *P;

Man kann auch Speicher für eine einzelne Variable allokieren. Dies ist aber erst dann sinnvoll, wenn ein Zeiger deutlich weniger Speicherplatz benötigt als die dynamisch anzulegende Variable.
Beispiel:
struct Person
{
 std::string Name, Vorname;
 long geboren;
};
...
Person *PP = new Person;
cin >> (*PP).Name;
oder cin >>PP->Name; // *PP.Name würde PP.Name dereferenzieren (falsch).

Der Pfeiloperator -> ersetzt bei Zeigern auf Structs die beiden Operatoren * und . sowie die runden Klammern.

Falls nicht mehr genügend Speicherplatz zur Allokation zur Verfügung steht, ist nach dem Standard der gelieferte Zeigerwert undefiniert. Visual C++ liefert in diesem Fall den Nullzeiger NULL. Der Nullzeiger stellt eine ungültige Referenz dar.

Freigabe von allokiertem Speicher

Wenn der allokierte Speicher nicht mehr benötigt wird, sollte er wieder freigegeben werden, um den freien Speicher zu vergrößern. Für die Freigabe dienen die Operatoren delete und delete[].

Mit dem ersten Operator (ohne Klammern) wird der Speicher einer einzelnen Variablen freigegeben. Der zweite Operator (mit den Klammern) dient zur Freigabe des Speichers eines Datenfeldes. In beiden Fällen muss dem Operator der Zeiger auf den Anfang des allokierten Speichers als Operand folgen.
Zu den obigen Beispielen:
delete PP;
delete[] DP;

Der Vollständigkeit wegen sei hier kurz erwähnt, dass zur Allokation auch die C-Funktionen malloc(), calloc() und zur Freigabe die C-Funktion free() zur Verfügung stehen.