首页 文章

堆栈与堆分配究竟如何在Rust中运行?

提问于
浏览
1

所以我理解这个工作原理的简单答案是本地的东西发生在堆栈中,盒子里的东西发生在堆上 .

但是,当您有更复杂的行为时会发生什么?

具体来说,让我们谈谈在FFI中保存了不确定时间的数据,然后必须从* mut c_void中复活 .

如果你'忘记'一个指针,使用std :: mem :: forget或std :: mem :: transmute()一个指向* const指针的指针结果是多么持久?

如果(例如)这是在函数内完成然后函数返回,堆栈是否被清除并且内存变为无效?

堆积分配的“Box”指针通常是否有效直到它们被销毁(例如使用read())?

我在IRC上被告知,这通常是正确的方法:

unsafe fn fp(v:Box<Foo>) -> *const c_void {
  return transmute(foo);
}

但是,看看libcore :: raw :: Box,Box与* const T并不是一样的;那真的好吗?

1 回答

  • 4

    如果你'忘记'一个指针,使用std :: mem :: forget或std :: mem :: transmute()一个指向* const指针的指针结果是多么持久?

    如果通过 fp 函数转换 Box 和transmute,只要您愿意,指针将保持有效,因为 transmute 正在消耗该值,因此释放内存的析构函数不会运行 . (至少,它是有效的,直到你将它转换回 Box<...> 让析构函数运行并释放内存 . )

    forget 没有返回值,它只是在不运行析构函数的情况下丢弃该值 .

    但请注意,转换为 *const c_void 需要额外注意,例如 Box<Foo> 内的 Foo 可能包含线程本地数据或引用,因此可能无效在线程之间传递,或永远存在 . (意思是指针本身永远存在/可用但是你喜欢,但它指向的数据可能没有 . )

    如果你开始编译 & 指针,你需要非常小心生命周期并且不要让它们从它们所指向的数据范围中逃脱(例如,你不能从函数返回指向局部变量的指针) .

    如果(例如)这是在函数内完成然后函数返回,堆栈是否被清除并且内存变为无效?

    堆栈没有被“清除”(即它没有明确归零),但是将任何指针用于不再存在的堆栈帧是无效的 .

    堆积分配的“Box”指针通常是否有效直到它们被销毁(例如使用read())?

    你需要更具体, ptr::read 不能直接在 Box 上调用,而在 *const c_void 上调用 ptr::read 肯定不会做任何有用的事情 .

    但是,看看libcore :: raw :: Box,Box与* const T并不是一样的;那真的好吗?

    raw::Box 完全不是正常 Box 的表示 . raw::Box 是旧 @ (现在为 Gc )类型的表示形式 . Box<T>literally a wrapper around a *mut T .

相关问题