021 Rust死靈書之異常安全性

linghuyichong發表於2021-05-07

本系列錄製的影片主要放在B站上Rust死靈書學習影片

Rust 死靈書相關的原始碼資料在github.com/anonymousGiga/Rustonomi...

Rust中主要考慮兩個層次的異常安全性:

  • 在非安全程式碼中,異常安全的下限是要保證不違背記憶體安全性,我們稱之為最小異常安全性;
  • 在安全程式碼中,異常安全性要保證程式時刻在做正確的事情,我們稱之為最大異常安全性。

大多數非安全程式碼都比較容易實現異常安全,因為它控制著程式執行的每個細節,而且大部分程式碼都不會Panic。但是需要特別注意的是類似於為初始化的陣列上反覆執行外部程式碼這樣的操作。例如如下程式碼:

//Vec::push_all的簡化版實現例子,說明情況
impl<T: Clone> Vec<T> {
    fn push_all(&mut self, to_push: &[T]) {
        self.reserve(to_push.len());
        unsafe {
            // 因為我們呼叫了reserve,所以不會出現溢位
            self.set_len(self.len() + to_push.len());

            for (i, x) in to_push.iter().enumerate() {
                self.ptr().offset(i as isize).write(x.clone());
            }
        }
    }
}

說明:但是此處,呼叫clone如果發生panic,則會導致分配的記憶體未初始化,而當Vec被訪問或者銷燬的時候,會讀取未初始化的記憶體。

解決辦法
上面的程式的問題在於先設定長度,然後再初始化,解決方式就是初始化之後再設定長度。

本作品採用《CC 協議》,轉載必須註明作者和本文連結
令狐一衝

相關文章