iT邦幫忙

2025 iThome 鐵人賽

DAY 24
0
Rust

把前端加速到天花板:Rust+WASM 即插即用外掛系列 第 24

Day 24|Borrow Checker:我不相信你

  • 分享至 

  • xImage
  •  

學 Rust 的人,大多在某個時刻被它的編譯器「教育」過。那個讓你崩潰的東西,就是 Borrow Checker。它不是程式跑起來才發現問題的工具,而是在你按下編譯鍵的瞬間,就會審問你:

這段程式碼,真的安全嗎?
你的記憶體,在這個時間點,誰擁有、誰借用、誰要歸還?

為什麼需要 Borrow Checker?

在 C 或 C++ 裡,你可以自由存取記憶體、釋放指標,但自由也代表風險 → dangling pointer、double free、或 memory leak 都可能在你不知道的情況下發生。

Rust 的哲學是:

「我不信任任何工程師喔 :)」

所以它建立一套「編譯期安全審查制度」── 讓程式在能執行之前,先保證記憶體不會出錯

這個制度的核心,就是 ownershipborrowing

那 Ownership 是什麼?

在 Rust 中,每個值都有「唯一的擁有者」,當擁有者離開作用域(scope)時,這個值會被自動釋放。

fn main() {
    let s = String::from("hello");
} // 這裡 s 離開作用域,記憶體自動釋放

沒有 free()、沒有 GC,卻保證安全。

但問題來了——如果我想暫時借用這個變數,不該被釋放,該怎麼辦?

這就進入下一個規則:borrowing

借用(Borrowing)規則:一次只能有一種權限

Rust 的借用系統只有兩種形式:

  1. 不可變借用(&T):你只能讀,不能改。
  2. 可變借用(&mut T):你可以改,但同時間只能有一個。

同時擁有可變與不可變借用會被禁止,

因為 Rust 要確保「有人在改,就不能有人在看」。

fn main() {
    let mut v = vec![1, 2, 3];
    let r1 = &v;         // 不可變借用
    let r2 = &mut v;     // error:同時存在可變與不可變引用
    println!("{:?}", r1);
    r2.push(4);
}

錯誤訊息可能會說:

cannot borrow `v` as mutable because it is also borrowed as immutable

這是 borrow checker 在保護你:

它寧願拒絕編譯,也不冒 data race 的風險。

如何讓它「放行」

Rust 不是不讓你改,而是要你清楚證明作用域不重疊

方法一:讓借用先結束

let mut v = vec![1, 2, 3];
{
    let r1 = &v;
    println!("{:?}", r1);
} // r1 在這裡結束
let r2 = &mut v;
r2.push(4);

方法二:用 split_at_mut() 切開資料區間

這樣 Rust 能確認兩個區塊不重疊。

let mut data = [0, 1, 2, 3, 4, 5];
let (a, b) = data.split_at_mut(3);
a[0] = 10;
b[0] = 20;

你不是在說服編譯器「相信你」,

而是提供形式化的證據

「這兩段記憶體真的不會互相踩到。」

RefCell 與 Unsafe

有時候,你真的需要在編譯期繞過檢查,例如:在物件導向模式或資料快取時。

這時可以使用 RefCell<T>UnsafeCell<T>

use std::cell::RefCell;

let x = RefCell::new(0);
{
    let mut b = x.borrow_mut();
    *b += 1;
}
println!("{}", x.borrow());

這樣做會讓「借用檢查」延後到執行期。但若你同時 borrow 兩次,Rust 會在 runtime panic。

Borrow Checker 的態度:它不信任任何人

Borrow Checker 不像其他語言的垃圾回收器,它不幫你收,也不幫你修。

它只負責一件事:

「我不相信任何人,除非你能證明你是安全的。」

這聽起來苛刻,但它的嚴格換來的結果是:

  • 沒有 data race
  • 沒有 double free
  • 沒有 dangling pointer
  • 而且不需要 GC

今天先這樣,昨天趕完這禮拜的作業數了一下我還有六份作業,真不給人活。下禮拜開考期中 哎


上一篇
Day 23|記憶體小技巧
下一篇
Day 25|Rust vs C++
系列文
把前端加速到天花板:Rust+WASM 即插即用外掛26
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言