Day 4:安全封裝 unsafe
學習目標
- 學會「用安全 API 包住 unsafe」
- 理解 FFI 與透過 unsafe 調 C 函式
- 建立「unsafe 盡量隔離」的心態
今日重點
安全封裝 unsafe
最好把所有 unsafe 集中,包成一個**安全公開的函式**,對外不露 unsafe。
這個函式對呼叫者安全(不變量在 assert 保證),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), ) } }
呼叫 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 不該讓借用規則被繞過出錯
練習
- 練習把
split_at_mut的變體(分 3 段)用安全 API 封裝。 - 寫一個呼叫
extern "C"malloc 的範例(了解即可,別真的跑)。 - 反思:為何「安全封裝 unsafe」是最佳實務。
自我檢查
- 會把 unsafe 包成安全函式
- 知道 extern 區塊呼叫 C
- 遵守「最小化、隔離、文件化」
- 理解 unsafe 的責任在開發者身上
深入連結
- The Book 第 19 章+Rustonomicon(FFI)