首页 > 解决方案 > 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

我对结果感到困惑有两件事:

  1. 函数的内存位置startend函数main()内部分别是0x7ffdcd2381f8和0x7ffdcd2381fc。函数变量的内存位置main是递增的。主函数调用getConst()函数,但函数内变量的位置getConst()是0x7ffdcd2381c8和0x7ffdcd2381cc,与函数内的变量相比,它们都是降序的main()。由于main函数调用getConst()函数,位置不getConst()应该在堆栈顶部main()吗?

  2. getConst()函数内,y是对 10 的 const 引用。据我了解,过程是,创建一个临时 int 变量,其值为 10,yreferences为它。从程序的输出中可以看出,两者都y指向t同一个内存位置。但是临时变量是在栈中定义的变量,不应该在getConst()函数返回后清理吗?如果是这样,如何t仍然可以获得正确的值?

标签: c++referenceconstants

解决方案


您的代码具有未定义的行为,因为它返回对临时变量的引用,因此任何事情都可能发生。

然而实际发生的情况可能是返回的引用基本上是一个指针,指向的内存不再有效,但指针本身只是一个数字,因此您能够打印它的值也就不足为奇了。打印引用的值可能会起作用,因为运行时不会“清理”释放的堆栈内存,这会浪费时间,当内存被重新使用时,它将被重新初始化。如果您调用包含未初始化变量的新函数,那么如果它们也具有与getConst. 这当然都是未定义的行为。

传统上堆内存从内存底部长大,堆栈从顶部向下长大,当两者相遇时你的程序内存不足。对于现代虚拟内存方案,这不再是字面上的情况,但堆栈通常仍然是一个固定大小的内存块,从后端使用到前端,因此新堆栈分配的地址低于旧的。这就是溢出堆栈变量如此危险的原因,您并没有覆盖未使用的内存,而是实际上覆盖了堆栈中较早的变量。


推荐阅读