污染

源:poisoning.md   Commit: 0e6c680ebd72f1860e46b2bd40e2a387ad8084ad

所有的非安全代码都必须保证最小异常安全性,但是并不是所有的类型都能保证最大异常安全性。即使一个类型保证了这一点,我们的代码也可能把它搞乱。比如,一个整数类型肯定是异常安全的,但是它自己没有语义。而一段代码可能在panic的时候没有正确更新整数的值,因此导致了不连续的状态。

这种情况通常没什么大不了的,因为异常发生时所有的东西都应该被销毁。例如,你给一个线程传递了一个Vec而线程panic了,这时Vec处于奇怪的状态其实也无所谓。反正它会被销毁掉并且永远消失。但是,一些类型会在发生panic的时候偷偷隐藏数据的值。

这些类型在遇到panic的时候可能会污染(poison)自己。污染没有什么特殊的含义,它通常只是指禁止其他人正常地使用它。最明显的例子是标准库中的Mutex类型。Mutex会在它的一个MutexGuards(Mutex在获取锁的时候返回的对象)因为panic而销毁的时候污染自己,这之后所有尝试给Mutex上锁的操作都会返回Err或者Panic。

从Rust惯常的角度看,Mutex的污染不算真正地保障安全性。污染是一种守护机制,在Mutex上锁期间遇到Panic后,禁止访问里面的数据。这种数据可能正被修改了一半,处于一种不连续或者不完整的状态。需要注意,只要数据正常写入了,即使使用这种类型也不会违反内存安全性。毕竟,这是最小异常安全的要求。

但是,如果Mutex包含一个没有设置任何属性的BinaryHeap,那么使用它的代码不太可能执行作者期望的行为。当然,程序也不可能正常运行下去。不过如果你能完全、绝对、百分之一百地肯定你可以用这些数据做点事情,Mutex还是提供了一个让你继续获得锁的方法。毕竟这是安全地,只不过可能没什么意义。