ProgrammierungRust Backend Entwickler

Erklären Sie, wie Borrowing und Aliasing in Rust funktionieren. Welche Einschränkungen gibt es für die gleichzeitige Verwendung von veränderlichen und unveränderlichen Referenzen, wie wird dies vom Compiler kontrolliert und was kann schiefgehen?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort

Borrowing (Ausleihen) in Rust ist ein Mechanismus, um eine Variable vorübergehend über Referenzen "zu leihen". Rust unterscheidet zwischen unveränderlichem Borrowing (&T) und veränderlichem Borrowing (&mut T). Es können beliebig viele unveränderliche Referenzen gleichzeitig existieren, aber nur eine veränderliche. Es ist nicht erlaubt, gleichzeitig veränderliche und unveränderliche Referenzen auf dasselbe Objekt zu haben.

Diese Regel gewährleistet, dass es keine Datenrennen zur Compile-Zeit gibt und macht Rust sicher für die nebenläufige Programmierung.

Beispiel:

let mut value = 5; let r1 = &value; let r2 = &value; // let r3 = &mut value; // FEHLER: &mut kann nicht erstellt werden, solange es ein & gibt println!("{} {}", r1, r2); // r3 ist bis zum Ende des Gültigkeitsbereichs von r1/r2 verboten

Fangfrage

Frage: Kann man in einem Gültigkeitsbereich eine &mut Referenz und beliebig viele & Referenzen auf dasselbe Objekt erstellen?

Typische falsche Antwort: Ja, aber nur, wenn sie sich in Bezug auf die Lebensdauer nicht überschneiden.

Richtige Antwort: Gleichzeitig kann es keine veränderliche und unveränderliche Referenz auf dasselbe Objekt geben (selbst wenn ihre Zugriffe sich statisch im Code nicht überschneiden), solange eine lebt — sind andere verboten. Die Sicherheit überprüft der Borrow Checker.

Beispiel:

let mut x = 10; let y = &x; let z = &mut x; // Fehler, y ist noch im Gültigkeitsbereich println!("{}", y); // y wird später benötigt

Beispiele für echte Fehler aufgrund mangelnden Wissens über die Feinheiten des Themas


Geschichte

In einem großen Projekt mit paralleler Datenverarbeitung entschloss sich ein Entwickler, unveränderliche Referenzen auf einen Vektor zu verwenden und versuchte dann, eine veränderliche Referenz zum Sortieren zu erhalten. Der Code funktionierte im Test, konnte aber nach der Umstrukturierung nicht mehr kompiliert werden, da die Lebensdauer der unveränderlichen Referenzen verlängert wurde.


Geschichte

In einem internen Dienst wurde eine Struktur über &mut geändert, während die Referenzen auf Felder für die spätere Übertragung in einen anderen Thread gespeichert wurden. Es trat ein Datenrennen und ein Absturz auf, weil die Borrow-Regeln nicht eingehalten wurden — Rust schützt nur zur Compile-Zeit davor, aber die Fehler lagen in unsafe-Blöcken, wo die Garantien aufgehoben sind.


Geschichte

Unzureichende Dokumentation der API: Die Bibliothek akzeptierte gleichzeitig & und &mut für verschiedene Felder der Struktur, aber aufgrund von Aliasing wurde die Invarianz verletzt und es traten schwer fassbare Bugs mit Diensten auf, die diese Bibliothek integrierten.