为什么这个指针算术(没有读取或写入这些指针后面的数据)是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
在Rust中,仅创建一个悬空引用是未定义的行为!这允许编译器围绕引用执行一些积极的优化,否则这是不可能的.
在这种特殊情况下,编译器生成代码align,该代码通过使用vtable中的值来计算字段的偏移量.因此它试图取消引用导致segfault的vptr.
要拥有悬空指针,不应使用引用,而应使用原始指针.你可以毫无问题地悬挂原始指针!
let fake: *const Bar<T> = std::ptr::null();
Run Code Online (Sandbox Code Playgroud)