c++ - const 引用的内存位置
问题描述
我有以下 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 的 const 引用。据我了解,过程是,创建一个临时 int 变量,其值为 10,yreferences
为它。从程序的输出中可以看出,两者都y
指向t
同一个内存位置。但是临时变量是在栈中定义的变量,不应该在getConst()
函数返回后清理吗?如果是这样,如何t
仍然可以获得正确的值?
解决方案
您的代码具有未定义的行为,因为它返回对临时变量的引用,因此任何事情都可能发生。
然而实际发生的情况可能是返回的引用基本上是一个指针,指向的内存不再有效,但指针本身只是一个数字,因此您能够打印它的值也就不足为奇了。打印引用的值可能会起作用,因为运行时不会“清理”释放的堆栈内存,这会浪费时间,当内存被重新使用时,它将被重新初始化。如果您调用包含未初始化变量的新函数,那么如果它们也具有与getConst
. 这当然都是未定义的行为。
传统上堆内存从内存底部长大,堆栈从顶部向下长大,当两者相遇时你的程序内存不足。对于现代虚拟内存方案,这不再是字面上的情况,但堆栈通常仍然是一个固定大小的内存块,从后端使用到前端,因此新堆栈分配的地址低于旧的。这就是溢出堆栈变量如此危险的原因,您并没有覆盖未使用的内存,而是实际上覆盖了堆栈中较早的变量。
推荐阅读
- c# - 使用HttpClient分块上传大文件到Controller,IFormFile总是为空
- dart - 动态更改 AlertDialog 标题 (showDialog())
- python - 如何使用熊猫转换我的 Excel 文件中的所有列
- r - 为通过 setRefClass 创建的对象扩展 as.data.frame 和 as.matrix 方法
- arrays - Google Scripts:使用单元格值填充多维数组
- powershell - 需要在powershell脚本中修剪一个url
- serialization - 有没有办法告诉 Serde 使用 struct 字段作为地图的键?
- java - 使用 SoapUi 生成的 POJO
- uwp - 如何在 .IDL 文件中声明枚举?
- xcode - 运行 git status 时,Mojave 更新后发生以下错误:“xcrun: error: invalid active developer path”