Rust 安全代码
安全与非安全代码对比 安全与非安全代码交互 非安全Rust能做什么 编写非安全代码数据布局
repr(Rust) 类型中的奇行种 可选的数据表达方式所有权
所有权 引用 别名 生命周期 生命周期的局限 省略生命周期 无界生命周期 高阶trait边界 子类型和变性 Drop检查 幽灵数据 分解借用类型转换
类型转换 强制类型转换 点操作符 显式类型转换 变形未初始化内存
未初始化内存 安全方式 Drop标志 非安全方式资源管理
基于所有权的资源管理 构造函数 析构函数 泄露展开
展开 异常安全性 污染并发
并发 竞争 Send和Sync 原子操作实现 Vec
实现 Vec 布局 内存分配 push和pop 回收资源 DeRef 插入和删除 IntoIter RawVec Drain 处理零尺寸类型 最终代码FFI
FFIRust 安全代码
安全与非安全代码对比 安全与非安全代码交互 非安全Rust能做什么 编写非安全代码数据布局
repr(Rust) 类型中的奇行种 可选的数据表达方式所有权
所有权 引用 别名 生命周期 生命周期的局限 省略生命周期 无界生命周期 高阶trait边界 子类型和变性 Drop检查 幽灵数据 分解借用类型转换
类型转换 强制类型转换 点操作符 显式类型转换 变形未初始化内存
未初始化内存 安全方式 Drop标志 非安全方式资源管理
基于所有权的资源管理 构造函数 析构函数 泄露展开
展开 异常安全性 污染并发
并发 竞争 Send和Sync 原子操作实现 Vec
实现 Vec 布局 内存分配 push和pop 回收资源 DeRef 插入和删除 IntoIter RawVec Drain 处理零尺寸类型 最终代码FFI
FFIRust 污染
所有的非安全代码都必须保证最小异常安全性,但是并不是所有的类型都能保证最大异常安全性。即使一个类型保证了这一点,我们的代码也可能把它搞乱。比如,一个整数类型肯定是异常安全的,但是它自己没有语义。而一段代码可能在panic的时候没有正确更新整数的值,因此导致了不连续的状态。
这种情况通常没什么大不了的,因为异常发生时所有的东西都应该被销毁。例如,你给一个线程传递了一个Vec而线程panic了,这时Vec处于奇怪的状态其实也无所谓。反正它会被销毁掉并且永远消失。但是,一些类型会在发生panic的时候偷偷隐藏数据的值。
这些类型在遇到panic的时候可能会污染(poison)自己。污染没有什么特殊的含义,它通常只是指禁止其他人正常地使用它。最明显的例子是标准库中的Mutex类型。Mutex会在它的一个MutexGuards(Mutex在获取锁的时候返回的对象)因为panic而销毁的时候污染自己,这之后所有尝试给Mutex上锁的操作都会返回Err或者Panic。
从Rust惯常的角度看,Mutex的污染不算真正地保障安全性。污染是一种守护机制,在Mutex上锁期间遇到Panic后,禁止访问里面的数据。这种数据可能正被修改了一半,处于一种不连续或者不完整的状态。需要注意,只要数据正常写入了,即使使用这种类型也不会违反内存安全性。毕竟,这是最小异常安全的要求。
但是,如果Mutex包含一个没有设置任何属性的BinaryHeap,那么使用它的代码不太可能执行作者期望的行为。当然,程序也不可能正常运行下去。不过如果你能完全、绝对、百分之一百地肯定你可以用这些数据做点事情,Mutex还是提供了一个让你继续获得锁的方法。毕竟这是安全地,只不过可能没什么意义。
下一章:Rust 并发
Rust作为一种语言,它其实并不知道怎么做并发或者并行。是标准库提供了操作系统线程和阻塞系统调用的支持。所有的平台都支持这些功能,基于这些一致的功能构建的抽象更容易被广泛接受。而消息传递、绿色线程、异步API这些则没有这么广 ...
AI 中文社