我询问了 Google 并在 StackOverflow 上做了一些研究。我的问题是,当我进入main()
在C++程序中调用函数并声明第一个变量,为什么该变量的地址在不同的执行过程中会有所不同?请参阅下面我的示例程序:
#include <iostream>
int main() {
int *a = new int;
int *b = new int;
std::cout << "address: " << a << " " << b << std::endl;
std::cout << "address of locals: " << &a << " " << &b << std::endl;
return 0;
}
执行1的结果:
address: 0xa32010 0xa32030
address of locals: 0x7fff10de2cf0 0x7fff10de2cf8
执行2的结果:
address: 0x1668010 0x1668030
address of locals: 0x7ffc252ccd90 0x7ffc252ccd98
执行3的结果:
address: 0x10e0010 0x10e0030
address of locals: 0x7ffd3d2cf7f0 0x7ffd3d2cf7f8
正如你所看到的,我在不同的执行中得到了不同的结果。输出的第一行对应于分配的内存的地址,这应该发生在堆中 - 如果每次都分配不同的地址,这对我来说有点有意义。然而,即使当我打印局部变量的地址(对应于第二行)时,结果仍然不同。
乍一看,我以为这是因为程序正在打印物理内存地址,但是这篇文章,虚拟内存或物理内存,反驳了我最初的想法。考虑到程序的执行是“相同的”,没有线程,没有用户输入等,是否有任何原因仍然存在不同地址的内存分配?
测试环境:
- Linux 14.04
- Mac OS X 10.10
在堆上分配时(使用new
运算符或malloc()
和朋友),你的程序必须要求操作系统分配你的堆内存。操作系统内存管理器中发生了很多幕后的事情(其实现细节大多超出了我的工资等级:垃圾收集、回收内存的整合等),它是一个好东西不必考虑它。
局部变量在堆栈上分配。传统上,堆栈分配是可重复的,但近年来这种情况发生了变化。地址空间布局随机化(ASR)是操作系统内存管理中相对较新的创新,它故意使堆栈分配中的内存地址(例如您所观察到的那些)在运行时尽可能具有不确定性。这是一个安全功能:这可以防止不良行为者利用堆缓冲区溢出,因为如果 ASLR 实现足够熵,谁知道溢出缓冲区的末尾会出现什么?
您为此和其他内存管理功能付出的代价是控制。在现代(非嵌入式)平台上对分配地址进行投注就像玩强力球:可能是一种有趣的干扰,但对于未来来说不是一个可行的计划。如果您的代码在 AVR-ISA 平台或类似平台上运行,那么赔率可能足够接近二十一点,以至于有人可能会被吸引去玩游戏以获胜(可以这么说)。
不管怎样,就我个人而言,我不是一个赌博者——正如我常说的,绅士们更喜欢堆栈分配。但这基本上就是您获得这些结果的原因。
感谢@T.C.获取链接,@SergeyA 获取建议。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)