Novus
Novus

Reputation: 187

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

I was testing some of Rust's unsafe functionality, mostly the std::ptr functions, to see the ways I could cause undefined behavior (just out of curiosity). In the example below I use std::ptr::read() to move the address stored in x into y without uninitializing x.

After the read I thought I had two pointers to the same location on the heap. I was under the impression that when I left the block where x is defined that x's destructor would be run causing y to point to freed memory. However, when I go and print the value of *y, it still prints the correct value of 10. I read the documentation but can't seem to figure out why this isn't UB. If anyone could clarify this for me, I would really appreciate.

PS. I come from a C background, so an explanation with respect to C might make it a tad easier to understand what is actually going on.

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);
}

Upvotes: 0

Views: 172

Answers (1)

Francis Gagn&#233;
Francis Gagn&#233;

Reputation: 65712

"Undefined Behavior" includes "it appears to work correctly". The worst mistake you can make when it comes to Undefined Behavior is interpreting a correct result as an absence of Undefined Behavior.

It doesn't work for me, by the way (and the value changes on every run).

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

Upvotes: 6

Related Questions