Während ein Programm ausgeführt wird, müssen Daten im Speicher abgelegt werden. Der benötigte Speicherplatz sowie die Ablageposition der Daten werden durch den jeweiligen Datentyp festgelegt. Beim Programmablauf werden zwei Speicherbereiche zur Datenhaltung verwendet: Stack (Stapelspeicher) und Heap (Haldenspeicher).
Stack (Stapelspeicher)
Der Stack ist ein zusammenhängendes Speicherarray, das dem Datenstrukturprinzip Last In, First Out (LIFO) – zuletzt abgelegt, zuerst entnommen folgt. Er speichert drei Arten von Daten:
- Werte von Variablen bestimmter Typen
- Aktueller Ausführungskontext des Programms
- An Methoden übergebene Parameter

Alle Speichervorgänge des Stacks werden automatisch vom System verwaltet, der Entwickler muss keine manuellen Eingriffe vornehmen. Das Verständnis der zugrundeliegenden Logik des Stacks erleichtert das Nachvollziehen des Programmablaufs sowie das Lesen der offiziellen C#-Dokumentation erheblich.
Kernmerkmale des Stacks
- Hinzufügen und Entfernen von Daten ist nur an der Stackspitze möglich
- Daten auf die Stackspitze legen: Push (Aufstapeln)
- Daten von der Stackspitze entnehmen: Pop (Abladen)
Eigenschaften des Stack-Speichers
- Extrem schnelle Speicherzuweisung und -freigabe, nutzt zusammenhängende Speicherblöcke
- Lebenszyklus an Methodenaufrufe gebunden: Ein Stack-Frame wird automatisch zerstört, sobald die Methode abgearbeitet ist
- Gespeicherte Inhalte: Werttyp-Variablen, Methodenparameter, lokale Variablen, Ausführungskontext

Um die Funktionsweise des Heaps besser nachvollziehen zu können, betrachten wir ein einfaches Codebeispiel
class Program
{
static void Main(string[] args)
{
int a = 10;
int b = 20;
int sum = Add(a, b);
}
static int Add(int x, int y)
{
return x + y;
}
}
Code-Sprache: JavaScript (javascript)
Die Logik dieses Beispiels ist unkompliziert. Ab der ersten Zeile der Einstiegsfunktion Main wird eine Integer-Variable a erstellt, in der zweiten Zeile folgt die Variable b. Zeile drei ruft die Funktion Add auf und übergibt die Werte von a und b an die Funktion. Innerhalb der Funktion erhält x den Wert von a, y den Wert von b; die Funktion gibt das Ergebnis von x + y, also 30, an die Aufrufstelle zurück und weist es sum zu. Sobald Add abgeschlossen ist, werden x und y vom Stack abgeladen, sum erhält den Wert 30; nach Beendigung von Main wird das Programm beendet. Im Folgenden gehen wir Schritt für Schritt den gesamten Push- und Pop-Vorgang im Stack durch.
Programmablauf und Push/Pop-Vorgänge des Stacks





Nach Abschluss von Add sind x und y lokale Parameter dieser Funktion, sie werden nacheinander per Pop entfernt, um Stack-Speicherplatz freizugeben und einen flüssigen Systemablauf zu gewährleisten.
Nach dem Abladen existieren x und y nicht mehr; der von Add zurückgelieferte Wert 30 gelangt zur Aufrufstelle und wird sum zugewiesen.




Merken Sie sich einen zentralen Punkt: Beim Ausführen einer Funktion werden Variablen von oben nach unten per Push auf den Stack gelegt, die Reihenfolge lautet a → b → Eintritt in Add → x → y. Nach Ende von Add werden x und y abgeladen, anschließend sum aufgestapelt; wenn Main schließt, folgen die Löschungen in umgekehrter Erstellreihenfolge: sum, b, a.
Heap (Haldenspeicher)
Der Heap ist ein großer Speicherbereich, der zur dynamischen Zuweisung von Speicherblöcken für Datenobjekte dient. Im Gegensatz zum Stack lassen sich Daten im Heap in beliebiger Reihenfolge einfügen und entfernen.
Ein Programm kann Objekte im Heap nicht manuell löschen. Der Garbage Collector (GC) der CLR (Common Language Runtime) räumt automatisch verwaiste, nicht mehr referenzierbare Objekte auf. Dadurch entfallen die fehleranfälligen manuellen Speicherfreigaben, die bei anderen Programmiersprachen erforderlich sind.
Der Heap lässt sich mit einem großen Schreibtisch vergleichen, auf dem man Gegenstände frei platzieren kann. Der zuvor beschriebene Stack hingegen gleicht einer Münzröhre mit nur einem Zugriffsend.

Ablauf der GC-Speicherbereinigung
- Das Programm erstellt drei Objekte im Heap und hält gültige Referenzen darauf
- Das Programm nutzt eines der Objekte nicht mehr, alle Referenzen darauf gehen verloren
- Der GC erkennt das referenzlose verwaiste Objekt und gibt seinen belegten Speicher frei
- Bereinigung abgeschlossen, der freigegebene Speicher kann neuen Objekten zugewiesen werden
Eigenschaften des Heap-Speichers
- Nicht zusammenhängender Speicher, Zuweisung läuft langsamer als beim Stack
- Lebenszyklus ist nicht an Methodengrenzen gebunden, zentral verwaltet durch den GC
- Gespeicherte Inhalte: Instanzen von Referenztypen (Klassen, Arrays, Delegaten etc.); im Stack werden nur die Speicheradressen der Heap-Objekte abgelegt
Ein praktisches Beispiel verdeutlicht diesen Vorgang. Wie bereits erläutert, liegen lokale Variablen von Grundtypen im Stack, während benutzerdefinierte Typen üblicherweise im Heap abgelegt werden. Sehen Sie sich folgenden Code an:
class Program
{
static void Main(string[] args)
{
int a = 10;
int b = 20;
Student tom = new Student("Tom", 12);
Student lucy = new Student("Lucy", 12);
}
}
class Student
{
//Membervariablen
private string name;
private int age;
//Konstruktor, wird später detailliert erklärt
public Student(string name, int age)
{
this.name = name;
this.age = age;
}
//Membermethode
public void DisplayInfo()
{
Console.WriteLine($"Name: {name}, Age: {age}");
}
}
Code-Sprache: JavaScript (javascript)
Die folgende Abbildung zeigt die Speicherablage der vier Variablen a, b, tom und lucy innerhalb von Main. Wie bei der Stack-Erläuterung läuft der Code von oben nach unten ab: zuerst wird a auf den Stack gepusht, danach b. Die Werte von a und b liegen direkt im Stack.


Beispielsweise liegen die Daten von tom im Heap-Block 00001, der Stack speichert die Adresse 00001, um später auf die Daten zugreifen zu können.
Sobald die Funktion Main abgeschlossen ist, wird die Adressreferenz lucy: 01010 im Stack per Pop entfernt und zerstört. Gelöscht wird aber nur die Adresse, nicht die eigentlichen Objektdaten im Heap. An diesem Punkt verliert das Heap-Objekt alle Referenzaufzeichnungen aus den Stack-Variablen.


Speicherbereiche im Überblick
Stack und Heap sind logische Speicherunterteilungen auf Softwareebene, keine physischen Hardwarepartitionen.
Stack und Heap stellen lediglich softwareseitige logische Aufteilungen des Speichers dar; der physische RAM-Hardware verfügt über keine dedizierten Hardwaremodule mit der Kennzeichnung „Stack-Bereich“ oder „Heap-Bereich“.
Der physische RAM besteht nur aus einheitlichen Speicherchips mit aufeinanderfolgenden physischen Adressen, es gibt keine Hardware-Markierungen zur Unterscheidung von Stack und Heap
Das Betriebssystem weist jedem laufenden Prozess einen separaten virtuellen Speicherbereich zu und unterteilt diesen virtuellen Speicher im Vorfeld in vier zentrale logische Segmente:
Code-Segment: Speichert kompilierte Programmanweisungen
Globales statisches Segment: Statische Variablen, Konstanten
Stack-Segment: Jeder Hauptthread und Unterthread des Programms besitzt einen eigenen unabhängigen Stack-Speicherblock
Heap-Segment: Großer gemeinsam genutzter Speicherpool für dynamische Zuweisungen
Der hier beschriebene Stack und Heap sind lediglich logische Bereiche, die das Betriebssystem jedem Prozess zuweist; es gibt keine hardwareseitige Trennung zwischen ihnen.
Stack vs. Heap