x86-64中的内存分配

时间:2019-02-25 21:24:44

标签: c gcc memory 64-bit

我只是想让我自己清楚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,有什么办法可以“预测”变量的位置?

2 个答案:

答案 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. C标准与ABI,可执行文件格式和加载程序无关。
  2. Advances in security通常意味着您不应该期望在现代操作系统上的用户模式程序的多次运行中看到相同的地址。

答案 1 :(得分:0)

您未指定操作系统。但是,操作系统在内存中的随机位置加载应用程序已变得很普遍。几十年来,编译器和链接器已经产生了可重定位的代码,但是从历史上看,这样做是为了使共享库可以从不同的程序加载到不同的位置。

现在,操作系统正在不同位置加载程序。这是一项安全措施。目的是防止破解者操纵特定的内存位置。

地址的最后几位相同是因为程序在页面边界上对齐。