Zum Inhalt springen

Ownership

Welches der folgenden ist KEINE Art von undefiniertem Verhalten?

Es kann vollkommen sicher sein, einen Zeiger auf freigegebenen Speicher in einem Stack-Frame zu haben. Das Wichtigste ist, diesen Zeiger nicht erneut zu verwenden, z.B. durch Lesen oder Freigeben.


fn add_suffix(mut s: String) -> String {
s.push_str(" world");
s
}
fn main() {
let s = String::from("hello");
let s2 = add_suffix(s);
println!("{}", s2);
}

Dieses Programm ist gültig, da s nach dem Verschieben in add_suffix nicht mehr verwendet wird.


fn main() {
let s = String::from("hello");
let s2;
let b = false;
if b {
s2 = s;
}
println!("{}", s);
}

Da s innerhalb der if-Anweisung verschoben werden könnte, ist es illegal, es in Zeile 8 zu verwenden. Obwohl die if-Anweisung in diesem Programm niemals ausgeführt wird, weil b immer false ist, versucht Rust im Allgemeinen nicht zu bestimmen, ob if-Anweisungen ausgeführt werden oder nicht. Rust geht einfach davon aus, dass sie ausgeführt werden könnten, und daher s verschoben werden könnte.


Angenommen, wir haben eine Funktion, die eine Box verschiebt, wie diese:

fn move_a_box(b: Box<i32>) {
// Dieser Bereich wurde absichtlich leer gelassen
}

Unten sind vier Code-Schnipsel, die vom Rust-Compiler abgelehnt werden. Stellen Sie sich vor, Rust würde stattdessen erlauben, diese Schnipsel zu kompilieren und auszuführen. Wählen Sie jedes Schnipsel aus, das undefiniertes Verhalten verursachen würde, oder wählen Sie “Keines dieser Schnipsel”, wenn keines dieser Schnipsel undefiniertes Verhalten verursachen würde.

Die Kernidee ist, dass, wenn eine Box an move_a_box übergeben wird, ihr Speicher nach dem Ende von move_a_box freigegeben wird. Daher:

  • Das Lesen von b über println nach move_a_box ist undefiniertes Verhalten, da es freigegebenen Speicher liest.
  • b einen zweiten Owner zu geben, ist undefiniertes Verhalten, da dies dazu führen würde, dass Rust die Box ein zweites Mal im Namen von b2 freigibt. Es spielt keine Rolle, ob die Bindung let b2 = b vor oder nach move_a_box erfolgt.

Das Ausführen von let b2 = b und anschließend println ist jedoch kein undefiniertes Verhalten. Obwohl b verschoben wird, werden seine Daten erst freigegeben, wenn move_a_box am Ende aufgerufen wird. Daher ist dieses Programm technisch sicher, obwohl es immer noch von Rust abgelehnt wird.