Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is there no segfault when accessing a variable that has gone out of scope using unsafe Rust?

I came across this strange phenomenon while playing with unsafe Rust. I think this code should make a segmentation fault but it does not. Am I missing something? I tried to set a pointer to a variable with a shorter lifetime and then dereference it.

// function that sets a pointer to a variable with a shorter lifetime
unsafe fn what(p: &mut *const i32) {
    let a = 2;
    *p = &a;
    //let addr = *p;    // I will talk about this later
    println!("inside: {}", **p);
}

fn main() {
    let mut p: *const i32 = 0 as *const i32;
    unsafe {
        what(&mut p);

        // I thought this line would make a segfault because 'a' goes out of scope at the end of the function making the address invalid
        println!("segfault? {}", *p);

        // Even more unsettling: I can increment the address and still dereference it.
        p = ((p as usize) + 1) as *const i32;
        println!("I'm definitely missing something: {}", *p);
    }
}

This program outputs:

inside: 2
segfault? {random number around 20000. probably uninitialized memory but why?}
I'm definitely missing something: {uninitialized memory}

If I uncomment the line

let addr = *p;

the second row becomes

segfault? 2

Why is there no segfault? Can the compiler extend the lifetime of a or the address p points at for safety? Am I missing some basic information about pointers in Rust?

like image 508
Turtle Turtleston Avatar asked Jan 21 '26 10:01

Turtle Turtleston


1 Answers

This isn't unique to Rust. See:

  • Why doesn't the following code produce a segmentation fault?
  • Accessing an array out of bounds gives no error, why?
  • Can a local variable's memory be accessed outside its scope?

TL;DR: you have lied to the compiler. Your unsafe block does not uphold the requirements of safe code. This means you have created undefined behavior and the program is allowed to do whatever it wants. That could mean:

  • it crashes (such as via a segfault)
  • it runs perfectly
  • it erases your hard drive
  • it empties your bank account
  • it generates nasal demons
  • it eats your laundry
  • etc.

Segfaults are never a guaranteed outcome. A segmentation fault occurs when you access memory that is outside of the chunk of memory your thread/process has. The memory of the stack is well inside of that chunk, so it's unlikely to trigger the case.

See also:

  • Why doesn't this Rust program crash?
like image 122
Shepmaster Avatar answered Jan 23 '26 06:01

Shepmaster