2006:Graydon Hoare 的個人專案——所有權構想的誕生#
事件#
2006 年,Mozilla 員工 Graydon Hoare 在工作之餘開始了 Rust 這個個人側專案。傳說中靈感來自一部壞掉的電梯:電梯的軟體(一個小型作業系統)因記憶體錯誤而當機——他體認到「連電梯都跑著作業系統,而系統軟體的記憶體安全問題無處不在」。
為何重要#
- 目標從一開始就極端明確:做出一種「既快又安全」的語言——速度比照 C++,但不需要垃圾回收就能保證記憶體安全。
- 當時的選項是二元對立的:C/C++ 快但危險;Java/C#/Go 安全但靠 GC、有執行期負擔與 GC 暫停,不適合系統程式設計。
- Rust 提出了第三條路:所有權(ownership)——每塊記憶體都有唯一的所有者,離開作用域即釋放,編譯期即可靜態證明安全。
理論與實用原因#
- 理論原因:基於線性型別/仿射型別(linear/affine types)理論——「值恰好使用一次」讓移動(move)語義可以靜態追蹤資源壽命;再加上 Cyclone(2001)的區域(region)型別,演變為後來的生命週期(lifetime)標註。
- 實用原因:Mozilla 需要重寫瀏覽器引擎(後來的 Servo)。統計顯示大型 C++ 專案約七成嚴重安全漏洞(CVE)源自記憶體錯誤——緩衝區溢位、懸垂指標、重複釋放、Use-After-Free。
程式範例#
C 的危險(Rust 要解決的問題)——懸垂指標,編譯器不會報錯,執行期才是未定義行為:
int* make_dangling() {
int x = 42;
return &x; // x 在函式結束後銷毀,回傳懸垂指標
}
Rust 的解法——同樣的程式在編譯期就被拒絕:
fn make_dangling() -> &i32 {
let x = 42;
&x // 編譯錯誤:x does not live long enough
} // 離開作用域時 x 釋放,引用不可能活過被引用者
所有權與移動(move)——值恰好有一個所有者:
let s1 = String::from("hello");
let s2 = s1; // 所有權「移動」給 s2
// println!("{}", s1); // 編譯錯誤:value borrowed after move
println!("{}", s2); // s2 離開作用域時自動釋放——不需要 free()
C++ 需要手動(或靠 RAII 慣例)做的事,Rust 由語言強制:
// C++:忘記 delete 就是記憶體洩漏,double delete 就是崩潰
char* buf = new char[100];
delete[] buf;
delete[] buf; // 未定義行為,編譯器不會擋
// Rust:Box 離開作用域自動釋放,不可能重複釋放(所有權已移動)
let buf = Box::new([0u8; 100]);
// 沒有 free、沒有 dangling、沒有 double free——全部由編譯器證明
彌補了什麼缺陷#
彌補了 C/C++「手動管理記憶體、編譯器不檢查壽命、錯誤要到執行期(甚至被攻擊時)才爆發」的根本缺陷,同時避免 Java/Go「GC 暫停、執行期、無法直接操作硬體」的系統程式設計限制。