我将原始指针传递给两个不同的闭包,并使用Box::from_raw()
将原始指针转换为引用,程序运行正常。
但是,在将原始指针转换为引用之后,应该按照文档所述自动调用析构函数:
此功能不安全,因为使用不当可能会导致内存问题。例如,如果在同一原始指针上两次调用该函数,则可能会出现double-free。
但是,即使在原始指针上调用了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);
}
在ABC
之后和handle
之前,handle1
为何不调用析构函数,因为Box::from_raw()
函数的description指定:
具体地说,
Box
析构函数将调用T
的析构函数并释放分配的内存。
为什么Box::from_raw()
在原始指针上多次工作?
答案 0 :(得分: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::into_raw
函数从另一个Box
那里获取的指针。
您也忽略了这方面。