跳轉到

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 暫停、執行期、無法直接操作硬體」的系統程式設計限制。

相關條目#