Unsafe Rustは、安全なRustのサブセットを拡張したもので、コンパイラが所有権、ライフタイム、およびエイリアシングの整合性を確認できない操作を使用できるようにします。主な使用例は、低レベルライブラリとの相互作用、FFI、手動メモリ管理、安全なRustモデルに収まらない抽象化の実装です。
unsafeの主な特徴:
unsafe { ... } または関数: unsafe fn some_func()例:
let x: i32 = 10; let ptr: *const i32 = &x as *const i32; unsafe { println!("Value: {}", *ptr); // rawポインタの逆参照 }
unsafeブロック内のコードは完全に危険であり、コンパイラによってチェックされないのか、それともコンパイラは依然としてborrowing checkerやその他のチェックを適用するのか?
答え: いいえ、unsafeブロック内では、コンパイラはRustの多くのルール(例えば、型、所有権のルール、構文)を引き続きチェックしますが、他の方法では許可されない操作のみを実行できます。borrow checkerを完全に無効化することはできません!
例:
let mut x = 0; let r1 = &mut x as *mut i32; // 禁止されている: let r2 = &mut x as *mut i32; // unsafe内でも、ミュータビリティが守られない場合はエラーが発生します。
物語
非同期ファイルライブラリでは、バッファのコントロールにrawポインタを使用しましたが、バッファのライフタイムを正しく追跡することを忘れました。その結果、ファイルを閉じるとポインタが「ダングリング」になり、アクセスが未定義の動作を引き起こしました(unsafeセクションはuse-after-freeから救ってくれませんでした)。
物語
独自のVecのような構造の実装では、プログラマーがunsafeを介して手動でバッファを拡張しました。オフセットのエラーにより、要素の不正なコピーとデータの破損が発生しました。これは、アラインメントと型のレイアウトが考慮されていなかったためです。
物語
スレッドのディスクリプタでは、適切な同期なしに静的ミュータブルポインタ(static mut)が使用されました。そのため、マルチスレッドモードで偶発的にデータレースが発生し、アプリケーションの sporadic crash を引き起こし、fuzzingによってのみ捕捉されました。