Memory 使用Box::from_raw()Box::to_raw()往返将无效指针生锈

Memory 使用Box::from_raw()Box::to_raw()往返将无效指针生锈,memory,rust,ffi,Memory,Rust,Ffi,我在尝试创建一些FFI助手代码时,对Box这个假定的简单用法进行了猛烈的抨击 这里的示例似乎给出了一个错误free():当与具有字段的结构一起使用时,指针无效 pub结构句柄(usize); impl句柄{ 发布fn from(obj:T)->Self{ 让boxed=Box::new(obj); 让mut ptr=Box::放入原始(装箱); Self::from_ptr_mut(&mut ptr) } pub fn from_ptr_mut(ptr:&mut)->Self{ 自身(ptr a

我在尝试创建一些FFI助手代码时,对Box这个假定的简单用法进行了猛烈的抨击

这里的示例似乎给出了一个错误
free():当与具有字段的结构一起使用时,指针无效

pub结构句柄(usize);
impl句柄{
发布fn from(obj:T)->Self{
让boxed=Box::new(obj);
让mut ptr=Box::放入原始(装箱);
Self::from_ptr_mut(&mut ptr)
}
pub fn from_ptr_mut(ptr:&mut)->Self{
自身(ptr as*mut T as usize)
}
pub fn to_box(self)->box{
让obj:*mut T T=self.to_ptr_mut();
不安全{Box::from_raw(obj)}
}
发布fn至(自)->*多{
self.0 as*mut T T
}
}
#[允许(死代码)]
结构崩溃{value:u64}
因碰撞而导致的impl下降{
fn下降(&mut自我){
println!(“崩溃下降”);
}
}
fn(){
设t=0{value:12};
设a=Handle::from(t);
设b=a.to_框::();
下降(b);
}
结构工程;
为工程而实施的项目{
fn下降(&mut自我){
println!(“放弃作品”);
}
}
fn工程(){
让t=工作;
设a=Handle::from(t);
设b=a.to_框::();
下降(b);
}
fn main(){
作品();
崩溃();
}
您可以将其粘贴到中,并查看它如何抛出带有错误
free():无效指针的中止


drop函数似乎在适当的时间被调用,但指针似乎在某种程度上无效

您最终在此处创建了一个双指针:

impl句柄{
发布fn from(obj:T)->Self{
让boxed=Box::new(obj);
让mut ptr=Box::放入原始(装箱);
Self::from_ptr_mut(&mut ptr)
}
pub fn from_ptr_mut(ptr:&mut)->Self{
自身(ptr as*mut T as usize)
}
...
}
Box::into_raw
返回一个指针,但随后您获取该指针的可变引用,并将该地址存储为
usize
。您应该只使用
*mut
返回的
Box::into_raw

带双指针的非工作代码编译的原因是,您的
from
from_ptr_mut
可以采用完全不同的
T
参数。如果我们将类型<代码> t>代码>从传递到一个具体的类型,那么在这种情况下,您调用的是<代码>从FuxPtRuMUT(其中<代码> u>代码>是代码> *MUT T ),类型为<代码>和MUT*MUT T 。 应该是这样的:

impl句柄{
发布fn from(obj:T)->Self{
让boxed=Box::new(obj);
将ptr=Box::放入原始(盒装);
Self::from_ptr_mut(ptr)
}
pub fn from_ptr_mut(ptr:*mut T)->Self{
自我(使用时的ptr)
}
...
}


即使我们处于
不安全的领域
您也可以让编译器通过将参数
T
绑定到您的
句柄
结构来为您做一些工作。通过这种方式,将静态阻止您加载与存储的类型不同的类型

在第二个示例中,您不必告诉编译器您正在检索la
a.to_框::()
,这很好,因为您不能通过指定错误的类型引入未定义的行为