unsafe 关键字

unsafe 关键字可以出现在几种不同的上下文: 非安全函数 (unsafe fn) ,非安全块 (unsafe {}) ,非安全 trait (unsafe trait) 和非安全 trait 实现 (unsafe impl) 中。 该关键字在不同的使用语境表达了不同的含义,以及是否启用 unsafe_op_in_unsafe_fn 代码分析:

  • 用于标记 定义 附加安全条件的代码 (unsafe fnunsafe trait) 。
  • 用于标记需要 满足 附加安全条件的代码 (unsafe {}unsafe impl ,没有 unsafe_op_in_unsafe_fnunsafe fn) 。

以下讨论这些情况的具体案例。 参见 关键字文档 以获取一些相关信息。

非安全函数 (unsafe fn)

非安全函数是在所有上下文和/或所有可能的输入上都非安全的函数。所表述的它们具有 附加安全条件 ,是指编译器不会检查所有调用者必须满足的要求。 例如, get_unchecked 具有附加的安全条件,即索引必须在边界内。非安全函数应该配有说明文档,以进行解释说明。

这样的函数必须以关键字 unsafe 为前缀,并且只能从 unsafe 块内部调用,或者在没有 unsafe_op_in_unsafe_fn 代码分析的情况下在 unsafe fn 中调用。

非安全块 (unsafe {})

代码块可以加上 unsafe 关键字,以允许调用 unsafe 函数或对原始指针进行引用。 默认情况下,非安全函数的函数体也被视为非安全块;这可以通过启用 unsafe_op_in_unsafe_fn 限制来改变。

通过将语句放入非安全块中,程序员声明他们已经满足了该块内所有语句的附加安全条件。

非安全块是非安全函数的逻辑对偶:非安全函数定义调用者必须满足的证明义务,而非安全块则声明所有相关证明义务已得到满足。 有许多方法可以满足证明义务;例如,可能存在运行时检查或数据结构不变,保证某些属性肯定为真,或者非安全块可以位于 unsafe fn 中,并使用其自己的证明义务来满足其调用方的证明义务。

非安全块用于包装外部库、直接使用硬件或实现语言中未直接出现的特性。 例如,Rust 提供了实现内存安全并发所需的语言特性,但标准库中的线程和消息传递的实现使用了非安全块。

Rust 的类型系统的动态安全要求有些保守,因此在某些情况下,使用安全代码会带来性能成本。 例如,双向链表不是树结构,只能在安全代码中使用引用计数指针来表示。 通过使用 unsafe 块来将反向链接表示为原始指针,可以在不使用引用计数的情况下实现。 (有关此特定示例的更深入探索,请参见 "使用多链表学习 Rust" )

非安全 trait (unsafe trait)

非安全 trait 是一种需要实现附加的安全条件的 trait,实现该 trait 必须遵守这些附加的安全条件。该非安全 trait 应该附带有说明这些附加安全条件的文档。

这样的 trait 必须以关键字 unsafe 为前缀,并且只能由 unsafe impl 块实现。

非安全 trait 实现 (unsafe impl)

在实现非安全 trait 时,实现必须以 unsafe 关键字为前缀。通过编写 unsafe impl,程序员表明他们已经注意到了 trait 所需的附加安全条件。

非安全 trait 实现是非安全 trait 的逻辑对偶:非安全 trait 定义了实现必须遵守的证明义务,而非安全实现则声明已经履行了所有相关的证明义务。