返回指向局部变量的指针时的堆栈行为
Stack behavior when returning a pointer to local variable
我有一个简单的例子,其中 Rust 的行为与我的心理形象不符,所以我想知道我错过了什么:
fn make_local_int_ptr() -> *const i32 {
let a = 3;
&a
}
fn main() {
let my_ptr = make_local_int_ptr();
println!("{}", unsafe { *my_ptr } );
}
结果:
3
这不是我所期望的。使用 The Stack and the Heap 中给出的符号,我希望堆栈帧看起来像这样:
Address | Name | Value
-----------------------
0 | a | 3
在make_local_int_ptr()
里面,但是在这一行之后,
let my_ptr = make_local_int_ptr();
由于 a
超出范围,我希望堆栈被清除,但显然没有。
此外,如果我在创建 my_ptr
和打印它的取消引用值之间定义另一个变量:
fn main() {
let my_ptr = make_local_int_ptr();
let b = 6;
println!("{}", b); // We have to use b otherwise Rust
// compiler ignores it (I think)
println!("{}", unsafe { *my_ptr } );
}
我的输出是:
6
0
这又不是我所期望的,我在想:
Address | Name | Value
-----------------------
0 | b | 6
在这种情况下我的输出将是:
6
6
甚至(在 C++ 和 Go 中我得到了这个结果):
Address | Name | Value
-----------------------
1 | b | 6
0 | a | 3
在这种情况下我的输出将是:
6
3
为什么我得到的输出是我得到的?为什么甚至允许返回指向局部变量的指针?变量超出范围,指针指向的值变得不可预测。
您根本不应该返回指向本地堆栈变量的指针。这样做是 未定义的行为,并且编译器可以完全自由地做任何它想做的事情。
当您说 unsafe
时,您向编译器承诺您将手动维护其所有预期的不变量...然后立即违背该承诺。
坦率地说:你违反了内存安全,所有赌注都被取消了。解决方案是不要那样做。
为了解释为什么您 可能 会看到这种行为,但是(同样,这是未定义的行为,没有任何保证):堆栈不是"cleared",因为它被零覆盖;只是不再阅读它是无效的。
此外,由于对 make_local_int_ptr
的调用已完成,编译器没有理由保留其堆栈 space,因此它可以重新使用 space 进行任何操作。由于调用 println!
?
,0
可能是
我有一个简单的例子,其中 Rust 的行为与我的心理形象不符,所以我想知道我错过了什么:
fn make_local_int_ptr() -> *const i32 {
let a = 3;
&a
}
fn main() {
let my_ptr = make_local_int_ptr();
println!("{}", unsafe { *my_ptr } );
}
结果:
3
这不是我所期望的。使用 The Stack and the Heap 中给出的符号,我希望堆栈帧看起来像这样:
Address | Name | Value
-----------------------
0 | a | 3
在make_local_int_ptr()
里面,但是在这一行之后,
let my_ptr = make_local_int_ptr();
由于 a
超出范围,我希望堆栈被清除,但显然没有。
此外,如果我在创建 my_ptr
和打印它的取消引用值之间定义另一个变量:
fn main() {
let my_ptr = make_local_int_ptr();
let b = 6;
println!("{}", b); // We have to use b otherwise Rust
// compiler ignores it (I think)
println!("{}", unsafe { *my_ptr } );
}
我的输出是:
6
0
这又不是我所期望的,我在想:
Address | Name | Value
-----------------------
0 | b | 6
在这种情况下我的输出将是:
6
6
甚至(在 C++ 和 Go 中我得到了这个结果):
Address | Name | Value
-----------------------
1 | b | 6
0 | a | 3
在这种情况下我的输出将是:
6
3
为什么我得到的输出是我得到的?为什么甚至允许返回指向局部变量的指针?变量超出范围,指针指向的值变得不可预测。
您根本不应该返回指向本地堆栈变量的指针。这样做是 未定义的行为,并且编译器可以完全自由地做任何它想做的事情。
当您说 unsafe
时,您向编译器承诺您将手动维护其所有预期的不变量...然后立即违背该承诺。
坦率地说:你违反了内存安全,所有赌注都被取消了。解决方案是不要那样做。
为了解释为什么您 可能 会看到这种行为,但是(同样,这是未定义的行为,没有任何保证):堆栈不是"cleared",因为它被零覆盖;只是不再阅读它是无效的。
此外,由于对 make_local_int_ptr
的调用已完成,编译器没有理由保留其堆栈 space,因此它可以重新使用 space 进行任何操作。由于调用 println!
?
0
可能是