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

Rust中指针未释放却值突变,此现象是否为Bug?

Rust悬空指针与未定义行为问题解析

问题代码

fn test() -> *const Vec<u8> {
    let b = vec![9_u8];
    let ret: *const Vec<u8> = &b;
    println!("ret ptr={:#p} inside {:#p}", ret, b.as_ptr());
    std::mem::forget(b);
    ret
}

fn main() {
    let a = test();
    let v = unsafe {
        &*a
    };
    println!("ret ptr={:#p} inside {:#p} value={}", v, v.as_ptr(), v[0]);
    println!("ret ptr={:#p} inside {:#p} value={}", v, v.as_ptr(), v[0]);
}

运行输出

ret ptr=0x00007fffc5d85690 inside 0x00005650a61cfaa0
ret ptr=0x00007fffc5d85690 inside 0x00005650a61cfaa0 value=9
ret ptr=0x00007fffc5d85690 inside 0x00005650a572a348 value=76

疑问解答

疑问1:为何该指针在Rust中未被释放就被垃圾回收?

首先纠正一个误解:Rust没有垃圾回收机制。问题核心在于内存区域的属性:

  • Vec<u8>变量b是分配在栈上的,当test函数执行完毕后,函数的栈帧会被销毁,栈上b占用的内存会被标记为可复用。
  • std::mem::forget(b)只是阻止了Vec的析构函数运行,也就是不会释放Vec指向的堆内存,但完全不影响栈上b自身的内存回收。
  • 你返回的指针ret指向的是栈上的b,所以函数返回后这个指针就成了悬空指针,指向的内存已经不属于当前有效的程序上下文了。

疑问2:最后一行输出中值突然发生变化,这是否属于Bug?

这不是Rust的Bug,而是**未定义行为(UB)**导致的不可预测结果:

  • 在main中通过unsafe { &*a }将悬空指针转为引用时,已经违反了Rust的安全规则——引用必须始终指向有效的、初始化的内存。
  • 第一次打印时,栈上原b的内存还没被其他操作覆盖,所以Vec的内部指针和数据值看起来正常;但第二次打印前,println!自身的调用会占用栈空间,覆盖了原栈上b的内容,导致Vec内部的指针被修改为随机地址,读取到的v[0]自然是随机值。
  • 未定义行为的结果没有任何保证,不同编译环境、优化级别下可能出现崩溃、数据错乱或其他诡异表现,这完全是代码违反内存安全规则导致的。

内容的提问来源于stack exchange,提问作者Nour-eddine Taleb

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 09:35:07