分享 Rust程式語言

Yenlin Chen
Yenlin Chen
6 min readMay 2, 2020

--

最近因為看到蠻多人推薦學C,所以讓我想推廣一下一個跟C, C++有差不多效能,但不需要擔心記憶體使用問題,又不需要garbage collector的程式語言Rust。它是第一個我看到同時上至網路服務,下至CLI程式、甚至作業系統核心都能撰寫的高階語言。

Rust是Mozilla Research (Firefox背後的公司的研究單位)在2010年發表的程式語言。主要發明它的背景有幾個原因,1) 記憶體管理問題,2) Thread safety。記憶體問題包含:Use after free, null pointer dereference, using uninitialized memory, double free, buffer overflow等等。Thread safety則是常見的:deadlock, race information loss due to race condition, etc.

記憶體管理問題

傳統上,記憶體管理方式分為兩大類別:1) 手動管理,2) 讓garbage collector管理。手動管理方式最大的優點是你擁有完全控制,但同時也是最大的缺點。從Mozilla、Microsoft公開的統計資料都顯示,大型C, C++ codebase中,很大一部分的安全性漏洞都源自於記憶體使用上的問題(Reference 1, 2)。Debug加上修復這些在production的問題,是非常耗時且昂貴的。

至於garbage collection,優點是軟體工程師不太需要擔心記憶體管理的問題,因為garbage collector會像一個跟在你程式身邊的清道夫,一段時間會出來大清掃一次,自動把不再需要的記憶體區塊還給作業系統。然而,這樣的便利性是有代價的。因為在程式執行時,進行大清掃不可避免地會影響到效能。

Rust選擇了第三個方式來做記憶體管理,Ownership。藉由Rust Compiler來強制施行(基本上就是給你的程式compile不過)以下三個原則,來做到memory safety,但又不需要garbage collector:

1) 任何Rust內的值,都屬於一個變數,稱為它的owner

2) 任何時候,每一個值都只有一個owner

3) 當一個owner goes out of scope,對應的值會被dropped (或freed)

基本上,你可以想像成,Rust compiler會在compile你的程式碼時,利用上述三個原則,來自動插入對應的memory allcation跟deallocation程式碼而不需要你介入。

Thread Safety

傳統上,有幾個處理方式:1) 手動管理 (如C, C++),2) runtime exception (如Java,3) 直接不給你multithread lol (如CPython中的GIL, global interpreter lock)。Rust再次有點反骨的,採取了跟這些不太一樣的方式:1) 利用前述的ownership原則,沒有任何值會同時有兩個owners,所以避免了race condition。2) 每個owner被限制只在一個thread上活動,3) 除了owner可以改變這個值外,其他人都只能唯讀這個值 (Rust中稱為immutable borrow)。

其他優點

作為一個現代的程式語言,如果單單只有上述這些優點是還不夠的。Rust的生態系統還為開發者們提供了許多便利的工具:

1. Rustup: 管理local Rust toolchains的工具。可以讓你方便地安裝不同版本的Rust,並在它們間切換。

2. Rust語言本身就提供Unit test, integration tests以及benchmarking的功能。所以你可以馬上開始撰寫production quality的程式。

3. Cargo: 有點類似Python中的pip及Pypi。Cargo是Rust一流的package manager。有寫過一定規模程式的工程師們,都可以體會dependency management是一個非常重要但又十分枯燥乏味的瑣事,因為必須考量它們彼此間的相容性,又要不定時的更新。Cargo以及其相應的Rust package registry網站, https://crates.io/,讓你只要提供一個dependency的名字及其版本,就可以從網路下載它並馬上帶入你正在進行的計畫。另外,cargo也負責管理,安裝以及編譯所有的dependencies。

4. Built-in formatter:有寫過任何沒有built-in格式formatter的程式語言 (如C, Java等等)的朋友,就可以體會當某個同事沒有使用大家共通的程式碼排版設定時,他的Pull request或code review就會出現一堆五花八門跟實際功能無關的改動,例如:移動大括號的位置,或者把一行長的程式碼分隔變成好幾行等等。Rust跟Go一樣,都自帶built-in formatter,rustfmt可以自動把你所有的程式碼根據官方建議的統一風格來排版。

5. 自動文件產生:對工程師來說是必要的工具,就是利用程式中的註解自動產生說明文件的rustdoc。除了產生格式統一且方便搜尋的文檔外,它還可以自動運行文件中的sample code,以確保你的說明文件跟實際的程式碼是搭得起來的。

6. Foreign function interface (FFI):Rust跟C之間可以互相呼叫,而且沒有任何效能影響。換句話說,你可以在Rust程式中,使用一個C library,或是在一個C程式中,呼叫一個Rust library中的function。

業界使用情況

最後,Rust現在被用在業界的哪些地方呢?Rust的創建公司Mozilla就用它重寫了Firefox瀏覽器中的重要元件;Amazon則利用Rust能夠跟低階軟硬體對接的特性,寫出輕量化虛擬機框架Firecracker;Dropbox則是把Rust用在客戶端運行的同步引擎及後端伺服器的壓縮演算法裡;Microsoft也正在實驗如何利用Rust提供的額外安全性,來重寫微軟作業系統核心裡的部分元件。

如果之後,有新專案可能需要類似C或C++的效能,但你又不想處理隨之而來的問題的話,試試看Rust吧!:)

Ref 1: https://msrc-blog.microsoft.com/2019/07/16/a-proactive-approach-to-more-secure-code/

Ref 2: https://hacks.mozilla.org/2019/02/rewriting-a-browser-component-in-rust/

Ref 3: https://hacks.mozilla.org/2019/02/fearless-security-thread-safety/

--

--

Yenlin Chen
Yenlin Chen

Software Engineer/Aspiring Videographer & Photographer