为什么指针算术是段错误的原因?

cha*_*pok 7 rust

为什么这个指针算术(没有读取或写入这些指针后面的数据)是segfault的原因?

#![allow(dead_code,unused_variables)]
use std::cell::Cell;

struct Bar<T: ?Sized> {
    a: Cell<usize>,
    value: T,
}

unsafe fn foo<T: ?Sized>(v: &T) {
    let fake: &Bar<T> = std::mem::zeroed();

    // segfault on this line
    // we are not reading or writing uninitialized data behind the reference, 
    // but only doing pointer arithmetic. We are not reading or writing 
    // uninitialized vtable, but only copy the vtable pointer.
    let fake_val = &fake.value;
}


fn main() {
    use std::any::Any;

    let some_ref: &Any = &42 as &Any;
    unsafe { foo(some_ref) };
}
Run Code Online (Sandbox Code Playgroud)

(在操场上)

输出: Segmentation fault

Luk*_*odt 9

在Rust中,仅创建一个悬空引用是未定义的行为!这允许编译器围绕引用执行一些积极的优化,否则这是不可能的.

在这种特殊情况下,编译器生成代码align,该代码通过使用vtable中来计算字段的偏移量.因此它试图取消引用导致segfault的vptr.


要拥有悬空指针,不应使用引用,而应使用原始指针.你可以毫无问题地悬挂原始指针!

let fake: *const Bar<T> = std::ptr::null();
Run Code Online (Sandbox Code Playgroud)