本文永久链接 – https://tonybai.com/2026/10/16/unsafe-rust-safety-boundary

大家好,我是Tony Bai。

【导读】

Rust 经常被称为“内存安全语言”,但这个结论有一个重要前提:代码必须遵守 Rust 的安全规则。

一旦进入 unsafe 世界,Rust 就把一部分责任交还给程序员。而 Robert Seacord 在 RustConf 2026 的演讲中进一步指出:问题甚至不只是“程序员有没有写对”,而是 Unsafe Rust 本身的语言语义,目前仍然没有完全确定。

这意味着,Rust 要真正进入汽车、操作系统内核等安全关键领域,还需要回答一个更基础的问题:究竟什么样的 Unsafe Rust 才是被语言正式定义、可以被工具和工程体系信任的代码?

【文章要点】

  • Safe Rust 很强,但不是万能的。Rust 可以阻止大量经典内存错误,但内存泄漏、栈溢出、逻辑错误等问题并不会因此消失。
  • Unsafe Rust 是 Rust 的另一面。裸指针、FFI、unsafe trait、底层汇编等能力都需要 unsafe,而这些能力恰恰是系统编程无法完全绕开的。
  • 真正棘手的是 Undefined Behavior。一旦发生 UB,编译器可以基于“UB 永远不会发生”进行优化,因此测试程序当前“看起来没问题”并不能证明代码正确。
  • Unsafe Rust 的部分语义仍处于未决状态。Rust 当前缺少一个完整的、正式定义 Unsafe Rust 行为的语言语义模型。
  • Pointer Provenance、Aliasing 等问题,是 Unsafe Rust 的深水区。一个指针不仅有地址,还有 provenance;相同地址并不意味着具有相同的访问权限。
  • Rust 正在建立自己的安全基础设施。FLS、Miri、MiniRust、a-mir-formality,以及 Tree Borrows 等项目,都在试图回答“Unsafe Rust 究竟允许什么”。
  • Rust 的下一阶段,不只是减少 unsafe,而是定义 unsafe。


Rust 最大的卖点之一,是内存安全。

但如果代码进入 unsafe,这套安全承诺还剩下多少?

在 RustConf 2026 上,Robert C. Seacord 带来了一场颇为“刺耳”的演讲——《Unsafe Rust》。

Seacord 不是典型的 Rust 布道者。他是 C 标准委员会主席、Woven by Toyota 的 Senior Staff Software Engineer,也是长期研究 C/C++ 安全编码的专家。正因为如此,这场演讲的视角非常特别:他不是在讨论“Rust 能不能替代 C”,而是在追问一个更加底层的问题:

当 Rust 进入汽车、内核等安全关键系统之后,我们究竟能对 Unsafe Rust 做出什么样的安全保证?

答案并不轻松:Rust 已经把 Safe Rust 做得非常安全,但 Unsafe Rust 的语言语义仍有相当一部分处于 unsettled(未决)状态。

这可能是今天理解 Rust 安全模型时,最值得关注的问题之一。

Rust 已经解决了很多 C 的痛点

先说一个 Seacord 明确认可的事实:Rust 的内存安全机制非常强大。

  • 所有权可以防止 Use-after-free 和 Double-free;
  • 生命周期分析可以帮助消除悬垂指针;
  • 借用规则以及 Send/Sync 可以在类型系统层面阻止大量 Data Race;
  • 数组访问有边界检查;
  • Option<T> 则迫使程序员显式处理“没有值”的情况。

这些恰恰是 C/C++ 长期以来最棘手的一批问题。

Seacord 甚至半开玩笑地说,Rust 有不少这样的特性,是他“很想偷到 C 里”的。

所以问题并不是:

Rust 有没有比 C 更好的内存安全机制?

当然有。

真正的问题是:

这些安全保证的边界在哪里?

Rust 的安全,并不是“什么都安全”

Rust 的安全模型首先建立在一个非常重要的划分上:

Rust 默认使用 Safe Rust。

而一旦需要某些底层能力,就必须进入 unsafe。

例如:

  • 解引用裸指针;
  • 调用 unsafe 函数;
  • 调用 C 函数和其他 FFI;
  • 实现 unsafe trait;
  • 操作 mutable static;
  • 操作 union;
  • 使用 asm! 或 naked_asm!。

Rust 2024 Edition 又进一步收紧了这个边界:一些过去虽然具有 unsafe 性质、但语法上没有明确出现 unsafe 的构造,现在也要求显式标记。例如 unsafe extern、#[unsafe(no_mangle)] 等。

这是一个很重要的改进。

因为在安全审查中,“搜索所有 unsafe”必须尽可能真的能够找到所有需要额外审查的地方。

但即使如此,Rust 的安全保证仍然不是万能的。

内存泄漏不会因为 Rust 而自动消失,深度或无限递归可能造成栈溢出,当然也仍然存在普通的逻辑错误。

因此:

Rust 提高了内存安全的下限,但并不是所有正确性、安全性和可靠性问题的银弹。

对于普通应用,这个区别可能并不致命。

但对于汽车、航空、医疗设备等安全关键系统,它就非常重要。

真正的问题:Undefined Behavior

Unsafe Rust 最值得警惕的概念,是 Undefined Behavior(UB,未定义行为)。

Seacord 给出的定义很直观:

一个操作没有合法的“下一状态”。

一旦进入 UB,编译器就可以假设这种情况不会发生,并基于这个假设进行优化。

于是事情就变得完全不同了。

更麻烦的是,UB 并不只影响发生 UB 的那一行代码。

编译器可能进行代码移动、重排等优化。如果某个 UB 允许编译器做出某些假设,那么这些假设可能影响整个程序的行为。

因此,不能简单地认为:

“我测试了一下,这段代码运行正常,所以没问题。”

Seacord 特别强调:

包含 UB 的程序,其测试结果不能用来证明程序行为。

甚至在 C/C++ 中,经常可以看到未经优化的代码运行正常,而开启优化之后却出现完全不同的结果。原因就在于优化器可以利用“UB 不会发生”这一前提。

对于安全关键软件而言,这意味着一个非常重要的结论:

消除 UB,是建立安全保证的前提。

Unsafe Rust 最大的问题:有些规则还没有完全确定

这里才进入 Seacord 演讲真正尖锐的部分。

Rust 当前缺少一个完整的形式化内存模型。这意味着,Unsafe 操作必须满足哪些不变量,其中相当一部分仍然没有最终确定。

Seacord 在演讲中反复使用了一个词:

Unsettled。

也就是:

目前还没有最终确定。

这和“编译器有 Bug”完全是两回事。

有些问题不是实现错了,而是语言本身还在决定规则应该是什么。

于是就出现了一个有趣的状态:

Seacord 甚至提醒,今天某个行为看起来能够工作,并不意味着未来的 Rust 版本一定继续允许这种行为。

当然,这里有一个重要的边界:Rust 不会把今天已经明确保证的定义行为,反过来变成 UB。

真正令人担忧的是那些尚未被语言最终确定的区域。

这也是为什么“当前编译器能跑”对于安全关键系统而言远远不够。

如果编译器升级后,语言对某个 unsettled 行为作出了新的解释,那么原来的代码就需要重新评估。

一个现实问题:到底谁说了算?

这可能是整场演讲里最值得工程师关注的一点。

假设你遇到了一个非常底层的 Unsafe Rust 问题。

你去哪里找答案?

可以看:

  • Rust Reference;
  • 编译器实际行为;
  • Miri;
  • Unsafe Code Guidelines;
  • 专家讨论;
  • 社区意见。

问题在于:

这些来源并不总是给出完全一致的答案。

Seacord 给出了一个很有代表性的例子:关于某些内存有效性问题,Rust Reference 的表述与 Miri 的实际判断可能存在差异。

因此,Miri 可以成为非常有价值的工具,但Miri 的行为并不自动等于 Rust 语言规范。

同样,某个版本的编译器允许某种行为,也不能证明这种行为就是 Rust 跨平台、跨编译器版本的语言保证。

这与 Seacord 熟悉的 C 世界形成了鲜明对比。

作为 C 标准委员会主席,他认为 C 至少存在一个相对明确的“权威来源”:标准委员会可以通过讨论形成共识,并对语言问题给出正式解释。

而 Rust 目前关于 Unsafe Rust 的“权威信息”相对分散。

这也是他认为 Rust 需要进一步解决的问题:

需要一个能够让程序员、编译器作者和工具开发者对语言规则形成一致理解的规范。

Rust 为什么又无法摆脱 Unsafe?

看到这里,可能有人会得出一个简单结论:

既然 unsafe 这么危险,那就不要用。

但这在系统编程里几乎是不可能的。

Rust for Linux 就是一个非常典型的例子。

目前 Linux Kernel 中 Rust 代码大约有 10% 被标记为 unsafe;而一些底层基础抽象中,Unsafe Rust 的比例甚至可能达到 30%~50%。

因为它必须面对:

  • 硬件;
  • 裸指针;
  • C ABI;
  • 内存管理;
  • 底层同步原语。

因此,一个典型的系统软件架构更接近:

Unsafe Rust 并不是 Rust 的失败。

恰恰相反,它是 Rust 能够进入系统编程世界的重要原因。

真正的问题是:

如何把危险尽可能压缩在一个很小、很清晰、可以被严格审查的边界里。

Pointer Provenance:指针不仅仅是一个地址

Unsafe Rust 的深水区之一,是 Pointer Provenance(指针来源/出处)。

传统 C 程序员往往把指针理解成一个地址:

0x12345678

但 Rust 的语义讨论要求我们考虑更多。

一个指针至少包含两个维度:

也就是说:

同一个地址,并不意味着同一个访问权限。

Seacord 给出的核心表述是:一次内存访问是否产生 UB,同时取决于 pointer 的 address 和 provenance;即使两个 pointer 指向相同地址,它们也可能因为 provenance 不同而产生不同结果。

为什么语言设计者要把问题搞得这么复杂?

因为编译器需要 Alias Analysis。

如果编译器能够知道:

“这两个指针不可能指向同一块有效对象。”

那么它就可以进行更大胆的优化。

所以这里实际上存在一个长期的张力:

你是希望保留所有历史上的底层指针技巧,还是希望编译器获得更强的优化能力?

Seacord 用一句很直白的话概括了这个矛盾:

鱼与熊掌难以兼得。

Unsafe Rust 应该怎么写?

Seacord 最后给出的建议,其实非常朴素。

也是他教授 C/C++ 安全编码时一直采用的方法:

只使用那些你明确知道其安全要求、并且能够验证这些要求的语言子集。

换句话说,不要把 unsafe 当成:

“编译器不让我做,所以我强行绕过去。”

而应该把它理解成:

这里需要程序员自己证明安全不变量。

这意味着,Unsafe Rust 应该尽可能:

  1. 小范围使用;
  2. 明确记录 Safety Invariant;
  3. 将 Unsafe 封装在 Safe API 后面;
  4. 使用 Miri 等工具辅助检查;
  5. 避免依赖尚未确定的语言行为;
  6. 在编译器升级后重新评估关键 Unsafe 代码。

这实际上也是 Rust 社区正在努力构建的方向。

FLS、Miri、MiniRust、a-mir-formality,以及 Stacked Borrows、Tree Borrows 等工作,都在尝试让 Rust 的底层语义更加清晰。

Rust 的下一场战役,不是消灭 Unsafe

我认为,这是 Robert Seacord 这场演讲最值得带走的一句话。

Rust 不可能消灭 Unsafe Rust。

系统编程需要它。

FFI 需要它。

操作系统需要它。

裸机开发需要它。

而且在某些追求极致性能的场景中,即使存在 Safe Rust 的实现,也可能因为性能原因需要进入 Unsafe Rust。

所以,Rust 真正需要完成的,并不是:

让 unsafe 消失。

而是:

让 unsafe 变得可定义、可验证、可审计。

对于普通应用开发者来说,Rust 当前已经提供了非常强大的安全保障。

但如果 Rust 要进一步进入汽车控制、航空、医疗、操作系统内核等安全关键领域,那么“编译器现在没有报错”显然还不够。

安全关键系统最终需要回答的是:

这段代码为什么安全?

而要回答这个问题,首先必须知道:

Rust 到底定义了什么是安全,什么是 UB,以及编译器究竟被允许做什么。

这也是 Unsafe Rust 下一阶段真正需要解决的问题。

Rust 已经花了十多年,把 Safe Rust 变成了一套令人惊叹的安全抽象。

接下来,它可能需要面对更加困难的一关:

给自己的 Unsafe 世界,画出一张足够精确的地图。

资料链接:https://www.youtube.com/watch?v=bTAEymCp7Ts


还在为写 Agent 框架频频死循环、上下文爆炸而束手无策?我的新专栏 《从0 开始构建 Agent Harness》 将带你:

  • 抛弃臃肿框架,回归“驾驭工程 (Harness Engineering)”的第一性原理
  • 用 Go 语言手写 ReAct 循环、并发拦截与上下文压缩引擎等,复刻极简OpenClaw
  • 构建坚不可摧的 Safety Middleware 与飞书人工审批防线
  • 在底层实现 Token 成本审计、链路追踪与自动化跑分评估
  • 从“调包侠”进化为掌控大模型边界的“AI 操作系统架构师”

扫描下方二维码,开启从 0 开始构建Agent Harness 的实战之旅。


还在为“复制粘贴喂AI”而烦恼?我的新专栏 《AI原生开发工作流实战》 将带你:

  • 告别低效,重塑开发范式
  • 驾驭AI Agent(Claude Code),实现工作流自动化
  • 从“AI使用者”进化为规范驱动开发的“工作流指挥家”

扫描下方二维码,开启你的AI原生开发之旅。


商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求,请扫描下方公众号二维码,与我私信联系。