021 Rust死灵书之异常安全性

Rust
276
0
0
2022-04-12

介绍

本系列录制的视频主要放在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被访问或者销毁的时候,会读取未初始化的内存。

解决办法

上面的程序的问题在于先设置长度,然后再初始化,解决方式就是初始化之后再设置长度。