Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Rust unsafe 關鍵字與底層程式設計分析

核心問題:「Rust 沒有 unsafe 關鍵字是寫不了底層代碼的」?

這個說法的正確性分析

✅ 部分正確的地方

確實,很多底層操作在 Rust 中需要 unsafe

  • 直接操作原始指標 - 解引用原始指標必須在 unsafe 區塊中
  • 呼叫外部 C 函式庫 - FFI (Foreign Function Interface) 需要 unsafe
  • 實作某些底層資料結構 - 如自訂的 LinkedList、內存分配器等
  • 直接操作硬體 - 如嵌入式系統中的記憶體映射 I/O
  • 某些效能優化 - 跳過邊界檢查等

❌ 但這說法過於絕對

  1. 很多底層代碼可以用 safe Rust 寫

    • 網路程式設計
    • 檔案系統操作
    • 多執行緒程式設計(使用標準庫)
    • 大部分的系統程式設計任務
  2. unsafe 是必要但最小化的工具

    • Rust 的設計理念是將 unsafe 限制在最小範圍
    • 通常只在最核心的部分使用 unsafe,然後包裝成安全的 API
    • 許多「底層」函式庫只在很小的部分使用 unsafe
  3. 實際例子

    • Linux kernel 的 Rust 程式碼確實需要 unsafe,但大部分邏輯仍是 safe 的
    • Tokio 這樣的非同步執行時,核心有 unsafe,但使用者程式碼幾乎都是 safe 的

更準確的說法

「某些特定的底層操作在 Rust 中確實需要 unsafe,但 Rust 的設計目標是盡可能用 safe 程式碼完成大部分工作,只在真正必要時才使用 unsafe。」


C/C++ 能做但 Rust 不能做的事?

理論層面:幾乎沒有

關鍵點:Rust 的 unsafe 基本上給了你 C 的所有能力:

  • 原始指標操作
  • 任意記憶體讀寫
  • 內聯組語
  • 呼叫任何 C ABI 的函式

因此理論上,任何 C 能做的底層操作,Rust + unsafe 都能做。

實務上的差異和限制

1. 某些未定義行為的「技巧」

// C 中某些程式設計師依賴的 UB 技巧
union type_punning {
    float f;
    uint32_t i;
};
// 在某些編譯器上"能用"但技術上是 UB

Rust 即使在 unsafe 中也會更嚴格地禁止某些 UB。

2. 編譯器特定的擴展

// GCC 的 computed goto (標籤作為值)
void* labels[] = {&&label1, &&label2};
goto *labels[i];
label1:
    // ...

Rust 不支援這類非標準擴展。

3. 某些極端的記憶體佈局控制

// C 中的 flexible array member
struct packet {
    int header;
    char data[];  // C99 的 FAM
};

Rust 需要用不同方式(DST 或 unsafe 技巧)來達成。

4. 變長陣列 (VLA)

void func(int n) {
    int arr[n];  // 執行時決定大小的堆疊陣列
}

Rust 故意不支援 VLA(認為不安全),需要用 Vecalloca 的 unsafe 包裝。

5. 某些嵌入式/即時系統的模式

// 直接在中斷處理程式中做複雜操作
// 某些 RTOS 特定的堆疊切換技巧

雖然 Rust 能做,但可能需要更多 unsafe 包裝。


這些「限制」大多是特性,不是缺陷

Rust 的設計哲學

  1. 明確標記危險操作 - unsafe 區塊讓危險代碼顯而易見
  2. 禁止未定義行為 - 即使在 unsafe 中也盡量防止 UB
  3. 提供安全的替代方案 - 如用 Vec 代替 VLA

實際成功案例

  • Linux Kernel - 正在整合 Rust,證明瞭 Rust 能做核心開發
  • 嵌入式開發 - Rust 在 ARM Cortex-M 等平臺很成功
  • 作業系統 - Redox OS 完全用 Rust 寫成
  • 遊戲引擎 - Bevy 等專案證明瞭高效能圖形程式設計可行

真正的權衡

開發體驗差異

層面C/C++Rust
安全性預設預設 unsafe預設 safe
開發速度簡單直接但容易出錯unsafe 部分需要更多思考
錯誤發現執行時才發現編譯時就能抓出大部分錯誤

生態系統成熟度

  • 某些特定領域(如某些 MCU)C 的工具鏈更成熟
  • 某些專有系統可能只提供 C/C++ SDK
  • 但 Rust 生態系統正在快速成長

學習曲線

  • 寫等效的 unsafe Rust 可能需要更深入理解記憶體模型
  • 但這種理解最終會產生更安全的代碼
  • 長期來看,維護成本通常更低

結論

技術層面

沒有 C/C++ 能做而 Rust + unsafe 絕對做不到的事。

實務層面

某些場景下 C/C++ 可能更方便,但這通常是生態系統或慣例問題,而非語言能力的根本限制。

核心觀點

Rust 的 unsafe 不是限制,而是一種精確控制的工具:

  • 它讓你能做所有底層操作
  • 同時清楚標記風險所在
  • 將危險操作最小化並封裝

最終答案

「Rust 沒有 unsafe 關鍵字是寫不了底層代碼的」這個說法有其道理,但更準確的理解是:unsafe 是 Rust 提供的一個強大工具,讓開發者能在需要時進行底層操作,同時保持代碼其他部分的安全性。這正是 Rust 的優勢所在。