unsafe
关键字
unsafe
关键字可以出现在几种不同的上下文中:不安全函数 (unsafe fn
)、不安全块 (unsafe {}
)、不安全特征 (unsafe trait
) 和不安全特征实现 (unsafe impl
)。它扮演着几种不同的角色,取决于它使用的位置以及是否启用了 unsafe_op_in_unsafe_fn
lint
- 它用于标记定义额外安全条件的代码 (
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
lint 的 unsafe fn
内部调用。
不安全块 (unsafe {}
)
代码块可以以 unsafe
关键字为前缀,以允许调用 unsafe
函数或解引用原始指针。默认情况下,不安全函数的主体也被认为是一个不安全块;这可以通过启用 unsafe_op_in_unsafe_fn
lint 来更改。
通过将操作放入不安全块中,程序员声明他们已经注意到了满足该块内所有操作的额外安全条件。
不安全块是不安全函数的对偶:不安全函数定义了调用者必须遵守的证明义务,而不安全块则声明块内调用的函数或操作的所有相关证明义务都已履行。履行证明义务的方法有很多;例如,可以进行运行时检查或数据结构不变量来保证某些属性一定是正确的,或者不安全块可以在 unsafe fn
内部,在这种情况下,该块可以使用该函数的证明义务来履行块内产生的证明义务。
不安全块用于包装外部库、直接使用硬件或实现语言中没有直接提供的功能。例如,Rust 提供了在语言中实现内存安全并发所需的语言功能,但标准库中线程和消息传递的实现使用了不安全块。
Rust 的类型系统是对动态安全需求的保守近似,因此在某些情况下,使用安全代码会带来性能成本。例如,双向链表不是树结构,在安全代码中只能用引用计数指针表示。通过使用 unsafe
块将反向链接表示为原始指针,可以在没有引用计数的情况下实现它。(有关此特定示例的更深入探讨,请参阅“使用太多链表学习 Rust”。)
不安全特征 (unsafe trait
)
不安全特征是指具有额外安全条件的特征,这些条件必须由特征的实现来维护。不安全特征应该附带文档,解释这些额外的安全条件是什么。
这样的特征必须以关键字 unsafe
为前缀,并且只能由 unsafe impl
块实现。
不安全特征实现 (unsafe impl
)
在实现不安全特征时,实现需要以 unsafe
关键字为前缀。通过编写 unsafe impl
,程序员声明他们已经注意到了满足特征所需的额外安全条件。
不安全特征实现是不安全特征的对偶:不安全特征定义了实现必须遵守的证明义务,而不安全实现则声明所有相关的证明义务都已履行。