unsafe
关键字
unsafe
关键字可以出现在几种不同的上下文: 非安全函数 (unsafe fn
) ,非安全块 (unsafe {}
) ,非安全 trait (unsafe trait
) 和非安全 trait 实现 (unsafe impl
) 中。
该关键字在不同的使用语境表达了不同的含义,以及是否启用 unsafe_op_in_unsafe_fn
代码分析:
- 用于标记 定义 附加安全条件的代码 (
unsafe fn
,unsafe trait
) 。 - 用于标记需要 满足 附加安全条件的代码 (
unsafe {}
,unsafe impl
,没有unsafe_op_in_unsafe_fn
的unsafe 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 定义了实现必须遵守的证明义务,而非安全实现则声明已经履行了所有相关的证明义务。