021 Rust死灵书之异常安全性

本文探讨了Rust编程中的异常安全性,特别是针对非安全代码和安全代码的异常安全标准。以Vec::push_all的简化实现为例,说明了在确保内存安全的同时,如何处理可能引发Panic的clone操作导致的未初始化内存问题。解决方案是通过改变初始化和设置长度的顺序来确保数据完整性。
摘要由CSDN通过智能技术生成

介绍

本系列录制的视频主要放在B站上Rust死灵书学习视频

Rust 死灵书相关的源码资料在https://github.com/anonymousGiga/Rustonomicon-Source

异常安全性

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被访问或者销毁的时候,会读取未初始化的内存。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值