Ownership
Kein Undefined Behavior
Abschnitt betitelt „Kein Undefined Behavior“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.
Ownership und String-Manipulation
Abschnitt betitelt „Ownership und String-Manipulation“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.
Konditionelles Verschieben
Abschnitt betitelt „Konditionelles Verschieben“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.
Box-Verschiebung und UB
Abschnitt betitelt „Box-Verschiebung und UB“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überprintlnnachmove_a_boxist undefiniertes Verhalten, da es freigegebenen Speicher liest. beinen zweiten Owner zu geben, ist undefiniertes Verhalten, da dies dazu führen würde, dass Rust die Box ein zweites Mal im Namen vonb2freigibt. Es spielt keine Rolle, ob die Bindunglet b2 = bvor oder nachmove_a_boxerfolgt.
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.