のドキュメントは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
またはb
(のa.disp()
代わりに)を使用しようとするt.disp()
と、初期化されていないメモリを使用している可能性があると正しくエラーが発生します。私が驚いたのはpanic
、の値に関係なく、常に正しいデストラクタを実行する (期待される文字列を出力する) ことi
です。
これはどのように起こりますか?ランタイムが実行するデストラクタを決定できる場合、実装された型に対して強制的に初期化する必要があるメモリに関する部分を、上記のリンクのDrop
ドキュメントから削除する必要がありますか?mem::uninitialized()