gpt4 book ai didi

返回指向局部变量的指针时的堆栈行为

转载 作者:行者123 更新时间:2023-11-29 08:10:40 25 4
gpt4 key购买 nike

我有一个简单的例子,其中 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

为什么我得到的输出是我得到的?为什么甚至允许返回指向局部变量的指针?变量超出范围,指针指向的值变得不可预测。

最佳答案

您根本不应该返回指向本地堆栈变量的指针。这样做是未定义的行为,编译器可以完全自由地做任何它想做的事。

当您说不安全时,您是在向编译器 promise 您将手动维护所有预期的不变量...然后立即违背该 promise 。

坦率地说:你违反了内存安全,所有赌注都没有了。解决方案是那样做。


要解释为什么您可能会看到这种行为,但是(同样,这是未定义的行为,没有任何保证):堆栈未“清除”它被零覆盖的感觉;只是不再从中读取是无效的。

此外,由于对make_local_int_ptr 的调用已完成,编译器没有理由保留其堆栈空间,因此它可以重新使用该空间。 0 可能是是因为调用了 println!?

关于返回指向局部变量的指针时的堆栈行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30826757/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com