Dev Study
← 解説「unsafe — コンパイラの保証を一部外す」に戻る

サンプルコードで身につける: unsafe — コンパイラの保証を一部外す

解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。

1生ポインタを作って読む

&value as *const i32 で生ポインタを「作る」のは普通のコードで書けて、* で「読む」操作だけが unsafe ブロックを要求します。有効な変数の参照から作った直後のポインタなので、この読み取りは安全に閉じています。まずは unsafe の境界線がどこに引かれているかを確認してください。

Rust

2*mut で書き換える

可変参照から *mut i32 を作れば、unsafe ブロックの中でポインタ越しの書き換えができます。借用チェッカーの管理外になるぶん、「ポインタが指す先が有効なまま使う」責任がプログラマに移ります。この例は有効な変数を直後に書き換えるだけなので、安全に閉じています。

Rust

3unsafe fn — 責任を呼び出し側へ

関数自体に unsafe を付けると、「引数のポインタが有効であることは呼び出し側が保証する」という契約になります。呼び出す側にも unsafe ブロックが必要になり、責任の所在がコードに明示されます。C ライブラリの関数を Rust から包むときによく見る形です。

Rust

4unsafe を安全な関数に閉じ込める

長さを検査してから unsafe で先頭要素を読む first は、外から見ればただの安全な関数です。「危険な操作を検査と一緒に内側へ閉じ込めて、安全な API だけを公開する」のが Rust 流の unsafe の使い方です。標準ライブラリの Vec なども内部はこの構造でできています。

Rust

5split_at_mut — 標準ライブラリの中の unsafe

1つの配列の前半と後半へ同時に &mut を取ることは、借用ルールの上では書けません。標準の split_at_mut は「重ならない2つの範囲だから安全」という事実を内部の unsafe で実装し、安全な API として提供しています。私たちは unsafe を書かずに、その恩恵だけを受けられます。

Rust