安全でない操作
この節では、まず公式ドキュメントから、「one should try to minimize
the amount of unsafe code in a code base.」(安全でないコードがコードベースに
しめる割合が最小になるよう努力しなければならない。)これを念頭に置いて、始めましょう。
Rustのunsafeアノテーションは、コンパイラによる保護を無効化するのに使います。
unsafeはおもにこれらの4つのことに使われます。
- 生ポインタを参照する
unsafeな関数やメソッドを呼び出す。(FFIから関数を呼び出すときも含みます。 この本の前の章も参照してください。)- 静的可変変数を変更する
- 安全でないトレイトを実装する
生ポインタ
生ポインタ*と参照&Tは似ていますが、参照は有効なデータを参照していることが
ボローチェッカーによっていつも保証されています。生ポインタを参照するにはunsafe
ブロックを使う必要があります。
fn main() { let raw_p: *const u32 = &10; unsafe { assert!(*raw_p == 10); } }
安全でない関数を呼び出す
いくつかの関数はunsafeブロックで定義されていて、これはコンパイラの代わりに
プログラマが正確性を管理しなければいけないことを意味します。一つの例は、最初の
要素のポインタと長さからスライスを作るstd::slice::from_raw_parts関数です。
use std::slice; fn main() { let some_vector = vec![1, 2, 3, 4]; let pointer = some_vector.as_ptr(); let length = some_vector.len(); unsafe { let my_slice: &[u32] = slice::from_raw_parts(pointer, length); assert_eq!(some_vector.as_slice(), my_slice); } }
slice::from_raw_partsは、メモリのポインタが有効で、かつすべて正しい型を持っている
という一種の仮定に基づいています。これはいつも成り立つとは限らず、もし成り立たなかった
ときの動作が未定義で、何が起こるかわかりません。