Unsafe関数の呼び出し
Unsafe関数の呼び出し
未定義の動作を回避するために満たす必要がある追加の前提条件がある関数またはメソッドは、unsafe
とマークできます。
extern "C" { fn abs(input: i32) -> i32; } fn main() { let emojis = "🗻∈🌏"; // SAFETY: The indices are in the correct order, within the bounds of the // string slice, and lie on UTF-8 sequence boundaries. unsafe { println!("emoji: {}", emojis.get_unchecked(0..4)); println!("emoji: {}", emojis.get_unchecked(4..7)); println!("emoji: {}", emojis.get_unchecked(7..11)); } println!("char count: {}", count_chars(unsafe { emojis.get_unchecked(0..7) })); // SAFETY: `abs` doesn't deal with pointers and doesn't have any safety // requirements. unsafe { println!("Absolute value of -3 according to C: {}", abs(-3)); } // UTF-8 エンコード要件を満たさない場合、メモリの安全性が損なわれます。 // println!("emoji: {}", unsafe { emojis.get_unchecked(0..3) }); // println!("char count: {}", count_chars(unsafe { // emojis.get_unchecked(0..3) })); } fn count_chars(s: &str) -> usize { s.chars().count() }
Unsafe関数の書き方
未定義の動作を回避するために特定の条件が必要な場合は、独自の関数を unsafe
とマークできます。
/// 指定されたポインタが指す値をスワップします。 /// /// # Safety /// /// ポインタが有効で、適切にアラインされている必要があります。 unsafe fn swap(a: *mut u8, b: *mut u8) { let temp = *a; *a = *b; *b = temp; } fn main() { let mut a = 42; let mut b = 66; // SAFETY: ... unsafe { swap(&mut a, &mut b); } println!("a = {}, b = {}", a, b); }
Unsafe関数の呼び出し
get_unchecked
, like most _unchecked
functions, is unsafe, because it can create UB if the range is incorrect. abs
is unsafe for a different reason: it is an external function (FFI). Calling external functions is usually only a problem when those functions do things with pointers which might violate Rust's memory model, but in general any C function might have undefined behaviour under any arbitrary circumstances.
この例の "C"
は ABI です(他の ABI も使用できます)。
Unsafe関数の書き方
実際には、swap
関数ではポインタは使用しません。これは参照を使用することで安全に実行できます。
アンセーフな関数内では、アンセーフなコードをunsafe
ブロックなしに記述することができます。これは #[deny(unsafe_op_in_unsafe_fn)]
で禁止できます。追加するとどうなるか見てみましょう。これは、今後の Rust エディションで変更される可能性があります。