为什么在放置的 Box 上使用 ptr::read() 不是未定义的行为?

Why isn't it undefined behavior to use ptr::read() on a dropped Box?

我正在测试 Rust 的一些不安全功能,主要是 std::ptr 函数,以查看我可能导致未定义行为的方式(出于好奇)。在下面的示例中,我使用 std::ptr::read() 将存储在 x 中的地址移动到 y 而不取消初始化 x.

读取后我认为我有两个指向堆上相同位置的指针。我的印象是,当我离开定义 x 的块时,x 的析构函数将是 运行,导致 y 指向释放的内存。但是,当我去打印 *y 的值时,它仍然打印出正确的值 10。我阅读了文档,但似乎无法弄清楚为什么这不是 UB。如果有人能为我澄清这一点,我将不胜感激。

PS。我来自 C 背景,所以对 C 的解释可能会让理解实际发生的事情变得更容易一点。

fn main() {
    let mut y: Box<i32>;

    {
        let x: Box<i32> = Box::new(10 as i32);
        unsafe {
            y = ptr::read(&x);
        }
    }
    // I thought the destructor (free) would be called here on x
    // making y point to invalid memory
    // However, the following call to println! still works
    println!("The value of y is {}", *y);
}

"Undefined Behavior" 包括 "it appears to work correctly"。当涉及未定义行为时,您可能犯的最严重错误是将正确结果解释为不存在未定义行为。

对我有用,顺便说一句(并且每个 运行 的值都会改变)。

$ cargo run
     Running `target/debug/so-ub`
The value of y is -500126584