You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中生成(非解引用)悬垂引用为何引发UB?能否被观测?

Rust中悬垂引用的未定义行为相关问题解答

《Rust参考手册》与《Rustonomicon》均明确规定:生成悬垂引用属于未定义行为(Undefined Behaviour,UB)。以下是触发该UB的示例代码:

fn main() {
    let p: std::ptr::NonNull<u8> = std::ptr::NonNull::dangling();
    #[allow(unused_variables)]
    let r: &u8 = unsafe { std::mem::transmute::<_, _>(p) };
}

通过Rust Playground中的Miri运行这段代码,会直接触发UB报错:

error: Undefined Behavior: constructing invalid value: encountered a dangling reference (address 0x1 is unallocated)
 --> src/main.rs:4:27
  |
4 |     let r: &u8 = unsafe { std::mem::transmute::<_, _>(p) };
  |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x1 is unallocated)
  |
  = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
  = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
  = note: BACKTRACE:
  = note: inside `main` at src/main.rs:4:27

针对你提出的两个问题,解答如下:

1. Rust中生成(非解引用)悬垂引用为何会导致UB?

Rust的引用存在核心不变式(invariants):所有引用必须始终指向有效的、对齐的、非空的内存;共享引用不能存在活跃的可变借用,可变引用不能存在其他任何借用。这些不变式是Rust编译器进行优化、保证内存安全的基础。

编译器会无条件信任这些不变式,比如它会假设引用指向的内存永远存活,因此可以大胆进行代码重排、常量传播、删除冗余检查等优化。如果允许生成悬垂引用,就直接破坏了这些不变式——编译器基于“引用有效”的假设生成的机器码,在实际运行时会因为引用悬垂而出现不可预测的行为。

此外,Rust的安全类型系统完全依赖这些不变式构建,生成悬垂引用相当于绕过了安全检查的边界,破坏了语言的内存安全模型,因此被定义为UB。

2. 能否在不解引用该引用的情况下观测到该UB?

可以。最直接的例子就是使用Miri这样的运行时验证工具:Miri会在程序执行过程中检查引用的有效性,一旦检测到悬垂引用被创建,就会立刻抛出错误,这个过程不需要解引用引用。

在实际的硬件执行环境中,虽然不会立刻触发崩溃,但编译器的优化可能会导致程序行为异常。比如编译器可能会基于“引用有效”的假设,将某些变量直接存入寄存器,或者删除它认为不必要的代码逻辑,最终导致程序输出不符合预期——而这一切都不需要你解引用那个悬垂引用。

内容的提问来源于stack exchange,提问作者Jonas Schäfer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 18:20:48