[rust]一些类型会在发生 panic 的时候偷偷变得不可用。

原文:https://doc.rust-lang.org/nomicon/poisoning.html

污染

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

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

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

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

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