的文档mem::uninitialized
指出了为什么使用该函数是危险/不安全的:调用drop
未初始化的内存是未定义的行为。
所以我相信这段代码应该是未定义的:
let a: TypeWithDrop = unsafe { mem::uninitialized() };
panic!("=== Testing ==="); // Destructor of `a` will be run (U.B)
但是,我编写了这段代码,它在安全的 Rust 中工作,并且似乎没有受到未定义行为的影响:
#![feature(conservative_impl_trait)]
trait T {
fn disp(&mut self);
}
struct A;
impl T for A {
fn disp(&mut self) { println!("=== A ==="); }
}
impl Drop for A {
fn drop(&mut self) { println!("Dropping A"); }
}
struct B;
impl T for B {
fn disp(&mut self) { println!("=== B ==="); }
}
impl Drop for B {
fn drop(&mut self) { println!("Dropping B"); }
}
fn foo() -> impl T { return A; }
fn bar() -> impl T { return B; }
fn main() {
let mut a;
let mut b;
let i = 10;
let t: &mut T = if i % 2 == 0 {
a = foo();
&mut a
} else {
b = bar();
&mut b
};
t.disp();
panic!("=== Test ===");
}
它似乎总是执行正确的析构函数,而忽略另一个。如果我尝试使用a
or b
(比如a.disp()
代替t.disp()
),它会正确错误地指出我可能正在使用未初始化的内存。令我惊讶的是,当panic
国王时,它总是运行正确的析构函数(打印预期的字符串),无论值i
是什么。
这是怎么发生的?如果运行时可以确定要运行哪个析构函数,是否应该Drop
从上面链接的文档中删除强制需要为已实现的类型初始化内存的部分mem::uninitialized()
?