为什么在使用不安全的Rust访问超出范围的变量时没有段错误?

Tur*_*ton 2 memory unsafe unsafe-pointers rust

我在玩不安全的Rust时遇到了这种奇怪的现象.我认为这段代码应该会出现分段错误,但事实并非如此.我错过了什么吗?我试图设置一个指向一个生命周期较短的变量的指针,然后取消引用它.

// 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

该计划输出:

inside: 2
segfault? {random number around 20000. probably uninitialized memory but why?}
I'm definitely missing something: {uninitialized memory}
Run Code Online (Sandbox Code Playgroud)

如果我取消注释该行

let addr = *p;
Run Code Online (Sandbox Code Playgroud)

第二行变成了

segfault? 2
Run Code Online (Sandbox Code Playgroud)

为什么没有段错误?为了安全起见,编译器可以延长生命周期a或地址p点吗?我错过了一些关于Rust指针的基本信息吗?

She*_*ter 8

这不是Rust特有的.看到:

TL; DR:你已经了编译器.你的unsafe块并没有坚持安全规范的要求.这意味着您已创建未定义的行为,并允许程序执行任何操作.这可能意味着:

  • 它崩溃了(例如通过段错误)
  • 它完美运行
  • 它会擦除你的硬盘
  • 它会清空您的银行帐户
  • 它会产生鼻子恶魔
  • 吃你洗衣服
  • 等等

Segfaults 永远不是一个保证的结果.一个分段错误,当你访问内存,内存块的线程/进程具有外发生.堆栈的内存完全位于该块内部,因此不太可能触发该情况.

也可以看看:

  • 不要忘记鼻腔恶魔 (2认同)