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

原始指针解引用:存在未定义行为的代码为何能编译?

为什么这段含未定义行为的UnsafeCell代码能编译通过?

你的代码确实存在明确的未定义行为(UB)——同时创建多个指向同一内存的可变引用,还直接通过裸指针修改数据,但它能编译通过的核心原因在于UnsafeCell的设计定位和Rust对unsafe代码的处理逻辑:

1. UnsafeCell的本质是“移交安全责任”

UnsafeCell是Rust中唯一允许突破“不可变数据不可修改”规则的核心类型,它的get()方法直接返回*mut T裸指针。这种设计的核心就是把内存安全的校验责任完全交给开发者——编译器不会对UnsafeCell内部的裸指针操作做额外安全检查,这正是unsafe代码块存在的意义:允许你在明确风险的前提下,执行安全代码禁止的操作。

2. unsafe块会放松借用检查器约束

在安全代码中,Rust的借用检查器会严格执行“同一时间只能有一个可变引用,或多个不可变引用”的规则,但进入unsafe块后,这个约束会被大幅放松:

  • 当你通过&mut *cell.get()从裸指针生成可变引用时,编译器不会跟踪这些引用是否指向同一块内存,它默认开发者会自行保证引用的安全性。
  • 编译器无法通过静态分析完全检测“多个可变引用共存”这类问题,因此不会在编译阶段拦截这类代码。

3. 未定义行为不属于编译错误

UB是运行时的内存安全问题,而非语法或编译规则错误。编译器的职责是确保代码符合语法规范,以及安全代码的内存安全,但对于unsafe代码,编译器仅检查语法合法性,不会验证其是否符合内存安全规则——哪怕代码存在UB,只要语法无误,编译器就会通过编译,而UB带来的后果(比如数据竞争、异常运行结果、程序崩溃)只会在运行时体现。

补充:这段代码的具体UB风险

你同时持有ptr1、ptr2两个可变引用,还直接通过*cell.get()修改数据,这违反了Rust内存模型的“可变引用独占性”规则。这种情况下,编译器可能基于“可变引用独占”的假设进行优化,导致程序运行结果不符合预期(比如修改操作被重复执行或直接忽略),甚至出现内存损坏。

内容的提问来源于stack exchange,提问作者Akanoa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 18:19:54