我具有以下C ++代码,并且正在运行g ++(Ubuntu 7.4.0-1ubuntu1〜18.04.1)7.4.0:
#include <iostream>
const int& getConst() {
int x = 10;
printf("x ptr: %p\n", &x);
const int &y = 10;
printf("y ptr: %p\n", &y);
return y;
}
int main() {
int start = 0;
printf("start ptr: %p\n", &start);
const int &t = getConst();
printf("t: %d\n", t);
printf("t ptr: %p\n", &t);
int end = 0;
printf("end ptr: %p\n", &end);
return 0;
}
此代码的输出如下:
root@78600f6683dd:/home/test/question# ./a.out
start ptr: 0x7ffdcd2381f8
x ptr: 0x7ffdcd2381c8
y ptr: 0x7ffdcd2381cc
t: 10
t ptr: 0x7ffdcd2381cc
end ptr: 0x7ffdcd2381fc
我对结果有两点感到困惑:
函数start
中end
和main()
的存储位置分别为0x7ffdcd2381f8和0x7ffdcd2381fc。 main
功能的变量的存储位置在递增。主要函数调用getConst()
函数,但是函数getConst()
中变量的位置是0x7ffdcd2381c8和0x7ffdcd2381cc,与main()
函数中的变量相比,它们的位置都在下降。由于main
函数调用getConst()
函数,因此getConst()
的位置是否不应该位于main()
的堆栈顶部?
在getConst()
函数中,y
是对10的常量引用。据我了解,过程是,创建一个temporary int variable的值为10,并且y references
。从程序输出中可以看出,y
和t
都指向相同的存储位置。但是临时变量是在堆栈中定义的变量,在getConst()
函数返回后不应该清除它吗?如果是这样,t
仍如何获得正确的值?
您的代码具有未定义的行为,因为它返回对临时变量的引用,因此任何事情都可能发生。
但是实际发生的情况可能是返回的引用基本上是一个指针,指向的内存不再有效,但是指针本身只是一个数字,因此可以打印其值就不足为奇了。打印引用的值可能会起作用,因为运行时不会“清理”释放的堆栈内存,这将浪费时间,当内存被重新使用时,它将被重新初始化。如果调用包含未初始化变量的新函数,则它们也具有与getConst
中设置的相同的值也就不足为奇了。这当然是所有不确定的行为。
通常,堆内存从内存的底部开始增长,而堆栈从顶部的向下增长,这两个条件相遇时,您的程序内存不足。对于现代的虚拟内存方案,从字面上不再是这种情况,但是堆栈通常仍然是固定大小的内存块,从头到尾使用,因此新堆栈分配的地址比旧的。这就是使堆栈变量溢出如此危险的原因,您不会覆盖未使用的内存,而实际上是在堆栈中更早地覆盖变量。