当我尝试打印main函数中第一个变量的地址时,我发现运行几次后结果始终是相同的。为什么?是在虚拟内存还是物理内存中?
#include <stdio.h>
int main()
{
int a;
printf("a's address is %p\n", &a);
return 0;
}
我希望每次输出都会有所不同,但实际输出始终为0028FF3C
答案 0 :(得分:5)
出于某些原因,在某些系统上启用了ASLR。
例如,在我的Linux / Debian / Sid x86-64上,您的程序每次都给出不同的地址:
repeat 10 tmp/sange
a's address is 0x7fff2768303c
a's address is 0x7ffc5d26a57c
a's address is 0x7ffcc0a4b2ac
a's address is 0x7ffeec95fd7c
a's address is 0x7ffefd5318dc
a's address is 0x7ffc544497bc
a's address is 0x7fff232f7dac
a's address is 0x7fff9dd3b65c
a's address is 0x7fff9e6858dc
a's address is 0x7ffc2876d4bc
要了解更多信息,请阅读有关undefined behavior(例如Lattner's blog),unspecified behavior的信息,并阅读有关操作系统的优秀教科书,例如Operating Systems: Three Easy Pieces(可免费下载)
也请阅读有关virtual address space的信息。
答案 1 :(得分:3)
由操作系统决定加载程序的位置以及变量的分配地址。
如果该地址是虚拟的物理地址,则它也取决于您的操作系统。它决定了如何管理内存。
答案 2 :(得分:2)
在任何普通的多用户操作系统中,您进程中的地址将是虚拟地址。这是因为,在普通的多用户操作系统中,操作系统使用虚拟地址空间来使程序彼此独立。
程序的地址空间部分由称为加载程序的进程建立,该进程将程序的初始数据和代码加载到内存中。一个简单的加载器将在一个固定的位置启动一个新程序的堆栈,每次加载程序时它将使用相同的起始位置。然后,程序运行时,a
将始终位于相同的地址。装载机以这种方式运行了很多年。
由于恶意人员有时可以利用已知的堆栈地址来攻击和破坏软件,因此某些加载程序现在在加载程序时使用随机地址。这称为地址空间布局随机化(ASLR)。当使用ASLR使用加载程序加载程序时,a
的地址因运行而异。