安全(Safety)

本章不講解任何語言知識點,而是對 Rust 安全理念的一些總結性說明。

安全,本身是一個相當大的話題。安全性,本身也需要一個局部性的定義。

Rust 的定義中,凡是 可能 會導致程序內存使用出錯的特性,都被認為是 不安全的(unsafe)。反之,則是 安全的(safe)

基於這種定義,C 語言,基本是不安全的語言(它是眾多不安全特性的集合。特別是指針相關特性,多線程相關特性)。

Rust 的這個定義,隱含了一個先決假設:人之初,性本惡。人是不可靠的,人是會犯錯誤的,即 Rust 不相信人的實施過程。在這一點上,C 語言的理念與之完全相反:C 語言完全相信人,人之初,性本善,由人進行完全地控制。

根據 Rust 的定義,C 語言幾乎是不安全的代名字。但是,從本質上來說,一段程序是否安全,並不由開發它的語言決定。用 C 語言開發出的程序,不一定就是不安全的代碼,只不過相對來說,需要花更多的精力進行良好的設計和長期的實際運行驗證。Rust 使開發出安全可靠的代碼相對容易了。

世界本身是骯髒的。正如,純函數式語言中還必須有用於處理副作用的 Monad 存在一樣,Rust 僅憑安全的特性集合,也是無法處理世界的所有結構和問題的。所以,Rust 中,還有 unsafe 部分的存在。實際上,Rust 的 std 本身也是建立在大量 unsafe 代碼的基礎之上的。所以,世界就是純粹建立在不純粹之上,“安全”建立在“不安全”之上。

因此,Rust 本身可以被認為是兩種編程語言的混合:Safe RustUnsafe Rust

只使用 Safe Rust 的情況下,你不需要擔心任何類型安全性和內存安全性的問題。你永遠不用忍受空指針,懸掛指針或其它可能的未定義行為的干擾。

Unsafe RustSafe Rust 的所有特性上,只給程序員開放了以下四種能力:

  1. 對原始指針進行解引(Dereference raw pointers);
  2. 調用 unsafe 函數(包括 C 函數,內部函數,和原始分配器);
  3. 實現 unsafe traits;
  4. 修改(全局)靜態變量。

上述這四種能力,如果誤用的話,會導致一些未定義行為,具有不確定後果,很容易引起程序崩潰。

Rust 中定義的不確定性行為有如下一些:

  1. 對空指針或懸掛指針進行解引用;
  2. 讀取未初始化的內存;
  3. 破壞指針重命名規則(比如同一資源的 &mut 引用不能出現多次,&mut& 不能同時出現);
  4. 產生無效的原生值:
    • 空指針,懸掛指針;
    • bool 值不是 0 或 1;
    • 未定義的枚舉取值;
    • char 值超出取值範圍 [0x0, 0xD7FF] 和 [0xE000, 0x10FFFF];
    • 非 utf-8 字符串;
  5. Unwinding 到其它語言中;
  6. 產生一個數據競爭。

以下一些情況,Rust 認為不屬於安全性的處理範疇,即認為它們是“安全”的:

  1. 死鎖;
  2. 存在競爭條件;
  3. 內存洩漏;
  4. 調用析構函數失敗;
  5. 整數溢出;
  6. 程序被中斷;
  7. 刪除產品數據庫(:D);

參考

下面一些鏈接,給出了安全性更詳細的講解(部分未來會有對應的中文翻譯)。

results matching ""

    No results matching ""