Rust記憶體安全解釋

banq發表於2024-04-04


是什麼讓 Rust 語言成為編寫快速、記憶體安全應用程式的最佳語言之一? Rust 的記憶體安全功能已融入到語言本身中。

Rust 如何以其他語言無法做到的方式保證記憶體安全?

Rust 記憶體安全:本機語言功能
關於 Rust 的記憶體安全功能,首先要了解的是,它們不是透過庫或外部分析工具提供的,這兩者都是可選的。 Rust 的記憶體安全功能已融入該語言中。它們不僅是強制性的,而且是在程式碼執行之前強制執行的。

在 Rust 中,記憶體不安全的行為不會被視為 執行時錯誤,而是被視為 編譯器錯誤。 Rust 中的所有問題(例如釋放後使用錯誤)在語法上都是錯誤的。此類無效程式碼永遠不會編譯,也根本不會投入生產。在許多其他語言(包括 C 或 C++)中,記憶體安全錯誤通常只能在執行時發現。

這並不意味著用 Rust 編寫的程式碼完全無懈可擊或萬無一失。一些執行時問題,例如競爭條件,仍然是開發人員的責任。但 Rust 確實消除了許多常見的軟體漏洞利用機會。

記憶體管理語言(例如C#、Java或Python)幾乎完全使開發人員無需進行任何手動記憶體管理。開發人員可以專注於編寫程式碼和完成工作。但這種便利需要付出一些其他代價,通常是速度或需要更長的執行時間。 Rust 二進位制檔案可以非常緊湊,預設以機器本機速度執行,並且保持記憶體安全。

Rust 變數:預設不可變
Rust 新手開發人員首先學到的一件事是,預設情況下所有變數都是不可變的——這意味著它們不能被重新分配或修改。必須將它們明確宣告為可變才能更改。

這可能看起來微不足道,但它的最終效果是迫使開發人員充分意識到程式中哪些值需要可變以及何時可變。生成的程式碼更容易推理,因為它告訴您可以更改什麼以及在哪裡更改。

預設不可變與常量的概念不同。不可變變數可以被計算,然後在執行時儲存為不可變的,也就是說,它可以被計算、儲存,然後不被更改。但是,在程式執行之前,常量必須在編譯時可計算。許多型別的值(例如使用者輸入)不能以這種方式儲存為常量。

  • C++ 的假設與 Rust 相反:預設情況下,一切都是可變的。您必須使用const關鍵字來宣告事物不可變。您可以const採用 預設使用的 C++ 編碼風格 ,但這隻會覆蓋您編寫的程式碼。
  • Rust 確保所有用該語言編寫的程式,現在和將來都預設假定不變性。

Rust 中的所有權、借用和引用
Rust 中的每個值都有一個“所有者”,這意味著在程式碼中的任何給定點,一次只有一件事可以對值具有完全的讀/寫控制。所有權可以暫時放棄或“借用”,但這種行為會被 Rust 的編譯器嚴格跟蹤。任何違反給定物件的所有權規則的程式碼都無法編譯。

將這種方法與我們在其他語言中看到的方法進行對比。

  • 在 C 語言中,沒有所有權:任何東西都可以隨時被任何其他東西訪問。如何修改事物的所有責任都由程式設計師承擔。
  • 在 Python、Java 或 C# 等託管語言中,所有權規則不存在,但這只是因為它們不需要。物件訪問以及記憶體安全由執行時處理。同樣,這是以速度或執行時的大小和存在為代價的。

Rust 的生命週期
Rust 中對值的引用不僅有所有者,還有生命週期——這意味著給定引用有效的範圍。在大多數 Rust 程式碼中,生命週期可以是隱式的,因為編譯器會跟蹤它們。但對於更復雜的用例,也可以顯式註釋生命週期。無論如何,嘗試訪問或修改其生命週期之外的內容或在其“超出範圍”之後都會導致編譯器錯誤。這再次防止了所有類別的危險錯誤透過 Rust 程式碼進入生產環境。

當您嘗試訪問理論上已被釋放或超出範圍的內容時,會出現釋放後使用錯誤或“懸空指標”。這些在 C 和 C++ 中非常常見。 C 在編譯時沒有正式強制執行物件生命週期。 C++ 有“智慧指標”之類的概念來避免這種情況,但預設情況下它們並沒有實現;您必須選擇使用它們。語言安全成為個人編碼風格或機構要求的問題,而不是語言完全確保的事情。

  • 對於 Java、C# 或 Python 等託管語言,記憶體管理是語言執行時的責任。這是以需要大量執行時間為代價的,有時還會降低執行速度。
  • Rust 在程式碼執行之前強制執行生命週期規則。

Rust 的記憶體安全是有代價的
Rust 的記憶體安全也有成本。第一個也是最大的就是學習和使用語言本身的需要。

切換到一門新語言從來都不是一件容易的事,對 Rust 的常見批評之一是它的初始學習曲線,即使對於經驗豐富的程式設計師也是如此。掌握 Rust 的記憶體管理模型需要時間和精力。即使在該語言的支持者中,Rust 的學習曲線也是一個不斷討論的話題。

C、C++ 以及所有其他語言都擁有龐大且根深蒂固的使用者群,這是他們經常被爭論的焦點。他們還擁有大量可以利用的現有程式碼,包括庫和完整的應用程式。不難理解為什麼開發人員選擇使用 C 語言:圍繞它們存在如此多的工具和其他資源。

也就是說,在 Rust 存在的十年左右的時間裡,它獲得了工具、文件和使用者社群,可以更輕鬆地跟上步伐。第三方“crate庫包”或 Rust 庫的集合已經非常廣泛並且每天都在增長。使用 Rust 可能需要一段時間的重新培訓和重新工具,但使用者很少會缺乏給定任務的資源或庫支援。
 

相關文章