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

问题描述 投票:1回答:1

我传递一个原始指针到两个不同的闭包,并使用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);
}

Rust Playground

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

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

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

rust smart-pointers unsafe
1个回答
4
投票

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函数从另一个Box::into_raw获取的指针。

你也忽略了这个方面。

© www.soinside.com 2019 - 2024. All rights reserved.