生ポインタの参照外し

ポインタの作成は安全ですが、参照外しには unsafe が必要です。

fn main() {
    let mut s = String::from("careful!");

    let r1 = &raw mut s;
    let r2 = r1 as *const String;

    // SAFETY: r1 and r2 were obtained from references and so are guaranteed to
    // be non-null and properly aligned, the objects underlying the references
    // from which they were obtained are live throughout the whole unsafe
    // block, and they are not accessed either through the references or
    // concurrently through any other pointers.
    unsafe {
        println!("r1 is: {}", *r1);
        *r1 = String::from("uhoh");
        println!("r2 is: {}", *r2);
    }

    // 安全でないため、NOT SAFE。このような記述をしないでください。
    /*
    let r3: &String = unsafe { &*r1 };
    drop(s);
    println!("r3 is: {}", *r3);
    */
}
This slide should take about 10 minutes.

unsafeブロックごとにコメントを記述し、そのブロック内のコードが行うアンセーフな操作がどのように安全性要件を満たしているのかを記述することをおすすめします(Android Rust スタイルガイドでも必須とされています)。

ポインタ参照外しの場合、これはポインタが valid でなければならないことを意味します。つまり、次のようになります。

  • ポインタは null 以外でなければならないこと。
  • ポインタは、(割り当てられた単一のオブジェクトの境界内で)参照外し可能でなければならない。
  • オブジェクトが解放されていないこと。
  • 同じロケーションに同時アクセスすることがないこと。
  • 参照をキャストしてポインタを取得した場合、基になるオブジェクトが存続しなければならず、他のいかなる参照を通してもそのメモリにアクセスがないこと

ほとんどの場合、ポインタも適切にアラインされる必要があります。

"NOT SAFE"というコメントがあるところは、よくあるUBバグの例を示しています。*r1 のライフタイムは 'static であるため、r3 の型は &'static String となり、s より長く存続します。ポインタからの参照の作成には細心の注意が必要です。