5.2 Unsafe

原文链接: https://rust-unofficial.github.io/too-many-lists/fifth-unsafe.html

这是一个严肃、庞大、复杂且危险的话题。严肃到我为此写了一整本别的书。

长话短说,任何语言一旦允许调用其他语言,实际上都是不安全的,因为你可以让 C 做任意糟糕的事。没错:Java、Python、Ruby、Haskell……面对外部函数接口(FFI),大家都不安全。

Rust 接受这一事实,把自己分成两种语言:Safe Rust 和 Unsafe Rust。到目前为止我们只用过 Safe Rust。它完全 100% 安全……除了它可以 FFI 到 Unsafe Rust。

Unsafe Rust 是 Safe Rust 的超集。在语义和规则上与 Safe Rust 完全相同,只是允许你做几件额外的、极其不安全、可能导致困扰 C 的未定义行为(Undefined Behaviour)的事。

再说一次,这是个非常大的话题,有很多有趣的边角情况。我真的不想深入(好吧,我想。我做了。读那本书)。没关系,因为对于链表,我们实际上几乎可以忽略其中的几乎全部。

旁白: 这是谎言,但在 2015 年似乎是真的。

我们将使用的主要 Unsafe 工具是裸指针。裸指针基本上就是 C 的指针。它们没有固有的别名规则。它们没有生命周期。它们可以为 null。它们可以未对齐。它们可以悬垂。它们可以指向未初始化的内存。它们可以和整数相互转换。它们可以转换指向不同类型。可变性?转换一下就行。几乎什么都可以,也意味着几乎什么都会出错。

旁白: 没有固有的别名规则,嗯?啊,青春的纯真。

这是些糟糕的东西,老实说你会更幸福地一辈子不碰它们。不幸的是,我们想写链表,而链表很糟糕。这意味着我们得用不安全的指针。

有两种裸指针:*const T 和 *mut T。它们意在对应 C 的 const T* 和 T*,但我们并不太在乎 C 怎么认为它们的含义。你只能把 *const T 解引用为 &T,但就像变量的可变性一样,这只是对错误用法的 lint。最多意味着你得先把 *const 转成 *mut。不过如果你没有权限修改指针所指的内容,你会倒霉。

总之,我们会在写代码的过程中更好地感受这些。现在,*mut T == &unchecked mut T!

最后修改 August 23, 2026: 更新 (499855b16)