我们到目前为止讨论过的代码都有Rust在编译时会强制执行的内存安全保证。然而,Rust还隐藏有第二种语言 ,它不会强制执行这类内存安全保证:这被称为 不安全Rust (unsafe Rust)。它与常规Rust代码无异,但是会提供额外的超能力。
尽管代码可能没问题,但如果Rust编译器没有足够的信息可以确定,它将拒绝代码。
不安全Rust之所以存在,是因为静态分析本质上是保守的。当编译器尝试确定一段代码是否支持某个保证时,拒绝一些合法的程序比接受错误的程序要好一些。这必然意味着有时代码 可能 是合法的,但如果Rust编译器没有足够的信息来确定,它将拒绝该代码。在这种情况下,可以使用不安全代码告诉编译器,“相信我,我知道我在做什么。”这么做的缺点就是你只能靠自已了:如果不安全代码出错了,比如解引用空指针,可能会导致不安全的内存使用。
另一个Rust存在不安全一面的原因是:底层计算机硬件固有的不安全性。如果Rust不允许进行不安全操作,那么有些任务则根本完成不了。Rust需要能够进行像直接与操作系统交互,甚至于编写你自已的操作系统这样的底层系统编程。
不安全的超能力
可以通过unsafe关键字来切换到不安全Rust,接着可以开启一个新的存放不安全代码的块。这里有5类可以在不安全Rust中进行而不能用于安全Rust的操作,它们称之为“不安全的超能力”:
- 解引用裸指针
- 调用不安全的函数或方法
- 访问或修改可变静态变量
- 实现不安全trait
- 访问 union 的字段
有一点很要重,unsafe并不会关闭借用检查器或禁用任何其它Rust安全检查:如果在不安全代码中使用引用,它仍会被检查。unsafe关键字只是提供了那5个不会被编译器检查内存安全的功能。但仍然能在不安全块中获得某种程序的安全。
再者,unsafe不意味着块中的代码就一定是危险的或者必然导致内存安全问题:其意图在于作为程序员你将会确保unsafe块中的代码以有效的方式访问内存。