我在玩“不安全的锈”时遇到了这个奇怪的现象。我认为这段代码应该造成分段错误,但它没有。我是不是遗漏了什么?我试图设置一个指向一个生命周期较短的变量的指针,然后取消对它的引用。
// 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);
}
}
此程序输出:
inside: 2
segfault? {random number around 20000. probably uninitialized memory but why?}
I'm definitely missing something: {uninitialized memory}
如果我取消对该行的注释
let addr = *p;
第二行变为
segfault? 2
为什么没有段错误?为了安全起见,编译器可以延长a
或p
指向的地址的生命周期吗?我是否遗漏了一些关于Rust中指针的基本信息?
发布于 2018-12-19 21:04:17
这并不是Rust独有的。请参见:
TL;DR:你欺骗了编译器。您的unsafe
代码块不支持安全代码的要求。这意味着你已经创建了未定义的行为,程序被允许做它想做的任何事情。这可能意味着:
>H123它会生成段错误
Segfaults永远不会保证结果(aSegfaults)。当您访问线程/进程所拥有的内存块之外的内存时,就会发生segmentation fault。堆栈的内存位于该块的内部,因此不太可能触发这种情况。
另请参阅:
https://stackoverflow.com/questions/53859055
复制