为什么不为 Box::from_raw() 调用析构函数?



我正在将原始指针传递给两个不同的闭包,并使用Box::from_raw()将原始指针转换为引用,程序工作正常。

但是,将原始指针转换为引用后,应按照文档所述自动调用析构函数:

此功能不安全,因为使用不当可能会导致内存问题。例如,如果在同一原始指针上调用函数两次,则可能会发生双重释放。

但是,即使在原始指针上调用Box::from_raw()两次后,我也能够访问对 ABC 的引用,并且它工作正常。

struct ABC {}
impl ABC {
pub fn new() -> ABC {
ABC {}
}
pub fn print(&self, x: u32) {
println!("Inside handle {}", x);
}
}
fn main() {
let obj = ABC::new();
let const_obj: *const ABC = &obj;
let handle = |x| {
let abc = unsafe { Box::from_raw(const_obj as *mut ABC) };
abc.print(x);
};
handle(1);
let handle1 = |x| {
let abc = unsafe { Box::from_raw(const_obj as *mut ABC) };
abc.print(x);
};
handle1(2);
}

锈游乐场

为什么在handle之后和handle1之前不调用析构函数ABC,因为Box::from_raw()函数的说明指定:

具体来说,Box析构函数将调用T的析构函数并释放分配的内存。

为什么Box::from_raw()在原始指针上多次工作?

TL;DR 你做错了。


将原始指针转换为引用

不,您正在将其转换为Box,而不是引用。

该程序工作正常

不是。你只是"幸运",内存不安全和未定义的行为不会触发崩溃。这可能是因为您的类型没有实际数据。

引用,应自动调用析构函数

否,当引用超出范围时,不会执行析构函数。

为什么不调用析构函数

它是,这是您的代码完全完全损坏和不安全的多种原因之一。

添加销毁期间要运行的代码:

impl Drop for ABC {
fn drop(&mut self) {
println!("drop")
}
}

你会看到它被调用了 3 次:

Inside handle 1
drop
Inside handle 2
drop
drop

我能够访问对ABC的引用

是的,这是不安全的。你违反了在编写unsafe代码时应该坚持的规则。您已经获取了一个原始指针,执行了一些操作使其无效,然后访问了现在无效的原始变量。

该文档还指出

传递给此函数的唯一有效指针是通过Box::into_raw函数从另一个Box获取的指针。

你也忽略了这一方面。

相关内容

  • 没有找到相关文章

最新更新