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
相关产品推荐
相关产品推荐

