为什么不为 Box::from_raw() 调用析构函数?
Why is the destructor not called for Box::from_raw()?
我将原始指针传递给两个不同的闭包,并使用 Box::from_raw()
将原始指针转换为引用,程序运行良好。
然而,在将原始指针转换为引用后,应该会自动调用析构函数,如文档所述:
This function is unsafe because improper use may lead to memory problems. For example, a double-free may occur if the function is called twice on the same raw pointer.
但是,即使在对原始指针调用 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
之前不调用析构函数,因为 description for Box::from_raw()
函数指定:
Specifically, the Box
destructor will call the destructor of T
and free the allocated memory.
为什么 Box::from_raw()
在原始指针上工作多次?
TL;DR 你做错了。
converting the raw pointer to a reference
不,您正在将其转换为 Box
,而不是引用。
the program is working fine
不是。您只是 "lucky" 内存不安全和未定义行为不会触发崩溃。这可能是因为您的类型没有实际数据。
to reference, the destructor should be called automatically
不,当references超出范围时,析构函数不会被执行。
Why is the destructor is not called
它是,这是您的代码完全损坏且不安全的多种原因之一。
销毁时添加代码运行:
impl Drop for ABC {
fn drop(&mut self) {
println!("drop")
}
}
你会看到它被调用了 3 次:
Inside handle 1
drop
Inside handle 2
drop
drop
I am able to access the reference to ABC
是的,这是不安全的。您违反了编写 unsafe
代码时应该遵守的规则。您使用了一个原始指针,做了一些使其无效的操作,然后访问了现在无效的原始变量。
文档也指出:
the only valid pointer to pass to this function is the one taken from another Box
via the Box::into_raw
function.
你也忽略了这方面。
我将原始指针传递给两个不同的闭包,并使用 Box::from_raw()
将原始指针转换为引用,程序运行良好。
然而,在将原始指针转换为引用后,应该会自动调用析构函数,如文档所述:
This function is unsafe because improper use may lead to memory problems. For example, a double-free may occur if the function is called twice on the same raw pointer.
但是,即使在对原始指针调用 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
之前不调用析构函数,因为 description for Box::from_raw()
函数指定:
Specifically, the
Box
destructor will call the destructor ofT
and free the allocated memory.
为什么 Box::from_raw()
在原始指针上工作多次?
TL;DR 你做错了。
converting the raw pointer to a reference
不,您正在将其转换为 Box
,而不是引用。
the program is working fine
不是。您只是 "lucky" 内存不安全和未定义行为不会触发崩溃。这可能是因为您的类型没有实际数据。
to reference, the destructor should be called automatically
不,当references超出范围时,析构函数不会被执行。
Why is the destructor is not called
它是,这是您的代码完全损坏且不安全的多种原因之一。
销毁时添加代码运行:
impl Drop for ABC {
fn drop(&mut self) {
println!("drop")
}
}
你会看到它被调用了 3 次:
Inside handle 1
drop
Inside handle 2
drop
drop
I am able to access the reference to ABC
是的,这是不安全的。您违反了编写 unsafe
代码时应该遵守的规则。您使用了一个原始指针,做了一些使其无效的操作,然后访问了现在无效的原始变量。
文档也指出:
the only valid pointer to pass to this function is the one taken from another
Box
via theBox::into_raw
function.
你也忽略了这方面。