Day 4:安全封裝 unsafe

學習目標

  • 學會「用安全 API 包住 unsafe」
  • 理解 FFI 與透過 unsafe 調 C 函式
  • 建立「unsafe 盡量隔離」的心態

今日重點

安全封裝 unsafe

最好把所有 unsafe 集中,包成一個**安全公開的函式**,對外不露 unsafe。

// 安全地切 split at mid(用 unsafe 做效能優化,但對外安全)
pub fn split_at_mut(slice: &mut [i32], mid: usize)
    -> (&mut [i32], &mut [i32])
{
    let len = slice.len();
    let ptr = slice.as_mut_ptr();
    assert!(mid <= len);

    unsafe {
        (
            std::slice::from_raw_parts_mut(ptr, mid),
            std::slice::from_raw_parts_mut(ptr.add(mid), len - mid),
        )
    }
}
這個函式對呼叫者安全(不變量在 assert 保證),unsafe 被藏在實作內。

呼叫 C 函式(FFI)

extern "C" {
    fn abs(input: i32) -> i32;   // 連結到 C 的 abs
}

fn main() {
    unsafe {   // 呼叫 extern 一定是 unsafe
        println!("{}", abs(-3));   // 3
    }
}

unsafe 使用守則

  • 最小化:unsafe block 越小越好
  • 文件化:註解清楚保證了哪些不變量
  • 隔離:集中封裝成安全 API
  • 不破壞不變量:unsafe 不該讓借用規則被繞過出錯

練習

  1. 練習把 split_at_mut 的變體(分 3 段)用安全 API 封裝。
  2. 寫一個呼叫 extern "C" malloc 的範例(了解即可,別真的跑)。
  3. 反思:為何「安全封裝 unsafe」是最佳實務。

自我檢查

  • 會把 unsafe 包成安全函式
  • 知道 extern 區塊呼叫 C
  • 遵守「最小化、隔離、文件化」
  • 理解 unsafe 的責任在開發者身上

深入連結

  • The Book 第 19 章+Rustonomicon(FFI)