Speicher und Garbage Collector in Rust: Wie eine Sprache ohne GC Ressourcen verwaltet

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Warum Rust keinen Garbage Collector benötigt, aber dennoch sicher ist?

\n\n

Wenn Entwickler, die an Python, Java oder C# gewöhnt sind, zum ersten Mal von Rust hören, erschreckt sie oft das Fehlen eines gewohnten Garbage Collectors (GC). „Wie soll das gehen? – denken sie. – Ohne GC kehren wir zurück in die Ära der manuellen Speicherverwaltung, mit Speicherlecks und Segmentation Faults?“

\n\n

Spoiler: Nein, das tun wir nicht. Rust bietet einen dritten Weg – das Ownership-System, das Speichersicherheit bereits zur Kompilierzeit garantiert. Keine Laufzeit, kein GC, keine hängenden Zeiger. Nur klare Regeln und ein Compiler, der verhindert, dass Sie sich ins Knie schießen.

\n\n

In diesem Artikel werden wir untersuchen, wie der Speicher in Rust funktioniert, was RAII, Ownership, Borrowing und Lebensdauer sind und warum all dies Rust zu einer der zuverlässigsten Sprachen für die Systemprogrammierung macht.

\n\n

Wie ist der Speicher in Rust aufgebaut: Stack und Heap

\n\n

Wie in jeder Low-Level-Sprache wird der Speicher in Rust in zwei Hauptbereiche unterteilt:

\n\n
    \n
  • Stack – schneller, in der Größe begrenzter Speicher, der nach dem LIFO-Prinzip funktioniert. Hier werden lokale Variablen, Funktionsargumente und Rücksprungadressen gespeichert.
  • \n
  • Heap – langsamerer, aber flexiblerer Speicher, der für Daten verwendet wird, deren Größe zum Zeitpunkt der Kompilierung unbekannt ist (z. B. String, Vec, Box).
  • \n
\n\n

In C++ entscheiden Sie selbst, wann Sie den Heap allozieren und freigeben (über new/delete). In Java oder Python erledigt dies der Garbage Collector für Sie, indem er das Programm regelmäßig anhält. Rust hingegen verwendet ein Ownership-System, das den Speicher automatisch freigibt, sobald eine Variable den Gültigkeitsbereich verlässt.

\n\n

Beispiel: Basis-Speicherallokation

\n\n
fn main() {\n    let s = String::from("Hallo, Welt!"); // Speicherallokation auf dem Heap\n    println!("{}", s);\n} // hier verlässt s den Gültigkeitsbereich, der Speicher wird freigegeben
\n\n

Beachten Sie: kein free() oder delete. Am Ende des Blocks fügt der Compiler implizit einen Aufruf des Destruktors ein – drop(). Dies wird als RAII (Resource Acquisition Is Initialization) bezeichnet – die Ressource wird bei der Initialisierung erfasst und bei der Zerstörung des Objekts freigegeben.

\n\n

Ownership: Die Hauptregel von Rust

\n\n

Das Ownership-System in Rust basiert auf drei einfachen Regeln:

\n\n
    \n
  1. Jeder Wert in Rust hat genau einen Besitzer (Owner).
  2. \n
  3. Wenn der Besitzer den Gültigkeitsbereich verlässt, wird der Wert gelöscht.
  4. \n
  5. Der Besitzer kann übertragen (Move) oder vorübergehend ausgeliehen (Borrow) werden.
  6. \n
\n\n

Klingt langweilig? Sehen wir uns an, wie das in der Praxis funktioniert.

\n\n

Move

\n\n
fn main() {\n    let s1 = String::from("hello");\n    let s2 = s1; // s1 wird nach s2 verschoben\n    // println!("{}", s1); // Fehler! s1 besitzt die Daten nicht mehr\n    println!("{}", s2); // OK\n}
\n\n

In C++ würde eine solche Zuweisung zu zwei Zeigern auf denselben Speicher führen – und zu einer doppelten Freigabe. In Rust verbietet der Compiler einfach die Verwendung von s1 nach dem Verschieben. Keine Speicherlecks, keine doppelten Löschungen.

\n\n

Copy

\n\n

Einfache Typen wie ganze Zahlen, boolesche Werte und Zeichen implementieren das Copy-Trait. Bei ihnen erzeugt die Zuweisung eine vollständige Kopie:

\n\n
fn main() {\n    let x = 42;\n    let y = x;\n    println!("x = {}, y = {}", x, y); // Beide sind verfügbar!\n}
\n\n

Warum das? Weil i32 auf dem Stack gespeichert wird und das Kopieren lediglich das Kopieren einiger Bytes bedeutet. Günstig und sicher.

\n\n

Borrowing und Referenzen

\n\n

Was tun, wenn Sie vorübergehend Zugriff auf Daten gewähren möchten, ohne das Ownership zu übertragen? Verwenden Sie Referenzen. Rust erlaubt es, einen Wert per Referenz auszuleihen.

\n\n
fn main() {\n    let s = String::from(                

Blogs

Buchempfehlungen