我只是想让我自己清楚x64架构上的c中的内存分配(如果我可以正确地称呼它)。
我有一个程序可以简单地输出变量在内存中的位置。我运行了几次,然后发现发生了一些奇怪的事情:
代码行:
printf("[*] test_val @ 0x%016llx = %d 0x%016llx\n", &test_val, test_val, test_val);
第一次:
[*] test_val @ 0x00005612f1edb050 = -72 0x00000000ffffffb8
第二次:
[*] test_val @ 0x000055ec3b64f050 = -72 0x00000000ffffffb8
第三次:
[*] test_val @ 0x00005577e99d4050 = -72 0x00000000ffffffb8
似乎变量test_int
的存储位置每次都不同,除了前2.5位(00005)和后1.5位(050部分不变)之外。
毫无疑问,但是在书中我所学到的这个地址一直都是不变的。主要区别在于本书是关于32位体系结构的。
我是否正确理解在x64系统中动态分配内存?考虑到我们知道最后1.5位,在这种情况下为050,有什么办法可以“预测”变量的位置?
答案 0 :(得分:2)
毫无疑问,但是在书中我所学到的这个地址一直都是不变的。
如果这本书实际上声称,则该地址在同一程序的多次运行中都保持不变,那是错误的。实际上,即使在一个程序的相同运行期间,具有自动存储持续时间的局部变量在运行 same 实例的多个调用中也可能会获得不同的地址。考虑:
void foo()
{
volatile int a = 12345;
printf("%p\n", (void *)&a);
}
void bar()
{
printf("In bar\n");
foo();
}
int main()
{
foo();
bar();
return 0;
}
我得到输出:
00B6FE58
In bar
00B6FE54
这是因为在输入bar
时,对foo
的调用在堆栈上创建了另一个框架,从而为a
提供了一个不同的地址。通常,我认为唯一可以安全推断的是,如果变量具有静态存储持续时间,则其地址应在整个单次运行中保持恒定程序。
关于为什么多次运行程序时会观察到不同的地址,原因是:
答案 1 :(得分:0)
您未指定操作系统。但是,操作系统在内存中的随机位置加载应用程序已变得很普遍。几十年来,编译器和链接器已经产生了可重定位的代码,但是从历史上看,这样做是为了使共享库可以从不同的程序加载到不同的位置。
现在,操作系统正在不同位置加载程序。这是一项安全措施。目的是防止破解者操纵特定的内存位置。
地址的最后几位相同是因为程序在页面边界上对齐。