rustunsafe

Dereferencing a pointer to a dropped value and the memory is still there


I'm playing with unsafe rust and trying to implement and I've found something I don't understand. I thought for sure I'd have a dangling pointer and that I'd get some kind of runtime error when trying to run this, but I don't.

fn main() {
    let s1 = String::from("s1");
    let s1_raw_ptr: *const String = &s1;
    drop(s1);
    
    unsafe {
        let s = &*s1_raw_ptr;
        println!("s recovered from raw pointer: {:?}", s);
    }
}

This outputs:

s recovered from raw pointer: "s1"

I thought that when a value goes out of scope in Rust that it is immediately cleaned up. How is it that dereferencing a raw pointer to a now-dropped value is working?


Solution

  • When a String is dropped in Rust, ultimately what ends up getting called is Allocator::deallocate on the system allocator. After this, using the data is undefined behaviour, so anything could happen! But in practice what tends to happen if there aren't any funky compiler optimizations is that you just get whatever data is stored in memory there. If there aren't any new allocations at that place, then you just get whatever data was there before.

    When a memory allocation is freed, nothing happens to the allocation. Clearing the data by setting it to all zero (or some other value) would be pointless, since any newly allocated memory always needs to be initialized by the user of that memory.