Kurz: Programme brauchen Arbeitsspeicher für Variablen, Listen und Objekte. Die Speicherverwaltung bestimmt, wer ihn anfordert und wieder freigibt: der Programmierer von Hand, eine automatische Müllabfuhr (Garbage Collector), Referenzzählung oder ein Besitzmodell wie in Rust.
Genauer: Fehler bei der Speicherverwaltung sind eine der häufigsten Ursachen für Abstürze und Sicherheitslücken: vergessene Freigaben (Speicherlecks), doppelte Freigaben, Zugriffe auf freigegebenen Speicher (use after free) und Zugriffe außerhalb von Arrays. Verschiedene Sprachen lösen das Problem unterschiedlich.
Im Detail
Stack und Heap
- Der Stack (Stapelspeicher) enthält lokale Variablen und Rücksprungadressen; er wächst und schrumpft automatisch mit jedem Funktionsaufruf und ist sehr schnell.
- Der Heap (Haldenspeicher) enthält Daten mit flexibler Lebensdauer, etwa wachsende Listen oder Objekte. Er muss verwaltet werden.
Strategien
| Strategie | Prinzip | Sprachen |
|---|---|---|
| Manuell | malloc/free, new/delete: Programmierer gibt frei | C, C++ (mit RAII), Pascal, Zig (Allocators), Assembler |
| Garbage Collector | Laufzeit findet unerreichbare Objekte und räumt auf | Java, C#, Go, Python (zusätzlich), JavaScript, Erlang, Haskell, Lisp |
| Referenzzählung | Jedes Objekt zählt, wie oft es verwendet wird; bei null wird freigegeben | Python, Swift (ARC), PHP, Nim (ORC), shared_ptr in C++ |
| Besitzmodell | Compiler prüft Besitz und Lebensdauer, freigegeben wird deterministisch | Rust |
| Statisch | Speicher steht zur Übersetzungszeit fest, kein Heap | Fortran (klassisch), COBOL, Teile von Ada |
Garbage Collection im Detail
Ein GC startet von „Wurzeln“ (Variablen, Stack) und markiert alles Erreichbare; der Rest ist Müll. Generationelle Verfahren nutzen, dass die meisten Objekte kurz leben. Nachteile: Speicherbedarf und mögliche kurze Pausen – moderne Sammler (G1, ZGC in der JVM, Go-GC) halten Pausen im Millisekundenbereich.
Warum Rust anders ist
Rust verlangt, dass jeder Wert genau einen Besitzer hat; Verweise („Borrows“) dürfen entweder mehrfach lesen oder einmal schreiben. Der Compiler beweist dadurch Speichersicherheit ohne Laufzeitkosten – dafür muss man das Modell erlernen. Ada/SPARK, Nim und Zig gehen eigene Wege zwischen Kontrolle und Sicherheit.
Tipps für den Alltag
- In Sprachen mit GC trotzdem Ressourcen wie Dateien und Verbindungen explizit schließen (
with,using,try-with-resources,Fun.protect). - In C/C++ moderne Hilfen nutzen (RAII,
unique_ptr, Sanitizer, Valgrind). - Speicherlecks mit Profilern finden, nicht raten.
Siehe auch: Laufzeitumgebungen, Typsysteme, Programmiersprachen im Überblick