1

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?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
maxjeffos
  • 63
  • 3
  • 3
    Dropping a `String` frees its heap allocation, which means that it either returns that memory to the OS or (more often) marks it as free for _future allocations_. It's undefined behavior to access the memory after it has been freed, but if you do that anyway, you may find the old contents there (until something else overwrites it). There is no requirement for freeing something "cleans it up", that would needlessly slow down deallocation. – user4815162342 Sep 26 '21 at 18:18
  • 4
    See this [hotel analogy answer](https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope/6445794#6445794) for why accessing data after its been deallocated can still look valid. – kmdreko Sep 26 '21 at 18:31
  • Thanks all for your input. That totally makes sense and is what I suspected. That hotel analogy is great and very memorable. – maxjeffos Oct 04 '21 at 10:45

1 Answers1

2

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.

smitop
  • 4,770
  • 2
  • 20
  • 53