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

Rust中移动裸指针指向的目标是否安全?双向图实测存疑

问题解答

这种行为不属于Rust的定义行为,绝对不能依赖,具体原因和正确做法如下:

  • 你的代码中,mytype最初在栈上分配,mytype.inner.parent保存的是栈上的地址。当调用Box::new(mytype)时,mytype被移动到堆内存中,此时栈上的原地址已经失效——Rust不保证栈上的旧内存会保留原有内容,也不保证后续不会被其他数据覆盖。
  • 测试中旧指针看似有效,只是未定义行为下的巧合:debug模式下编译器不会做激进优化,栈内存可能暂时没被重用,但这不是语言层面的保证。切换到release模式、更换编译器版本或平台,程序可能直接崩溃、输出错误值,或者出现其他不可预测的行为。
  • 正确的做法是先将值放入Box,再设置父指针——因为Box分配的堆内存地址是稳定的(除非Box被销毁),此时指针指向的是不会移动的堆地址:
fn main() -> Result<(), ()> {
    let m = test();
    println!("MT:{}, IT:{}, PTR_MT:{}", m.j, m.inner.i, unsafe { (*m.inner.parent).j });
    Ok(())
}

fn test() -> Box<MyType> {
    let mut mytype = Box::new(MyType {
        inner: MyInnerType { parent: std::ptr::null_mut(), i: 5 },
        j: 69
    });
    println!("MT:{}, IT:{}", mytype.j, mytype.inner.i);
    // 此时mytype指向堆上的地址,设置parent指针
    mytype.inner.parent = mytype.as_mut();
    mytype
}

struct MyType {
    inner: MyInnerType,
    j: i32
}

struct MyInnerType {
    parent: *mut MyType,
    i: i32
}
  • 即便如此,使用裸指针仍然需要严格遵守安全规则:确保父节点的生命周期始终长于子节点,避免出现悬垂指针。如果需要更安全的双向图实现,也可以考虑使用Rc<RefCell<T>>或Arc<Mutex<T>>这类智能指针,在安全的前提下实现双向引用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 01:27:15