我只是想让自己清楚地了解 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)这一事实,是否有任何方法可以“预测”变量的位置?
最佳答案
There would've been no question, but in the book I'm learning by this address is constant all the time.
如果这本书实际上声称地址在同一程序的多次运行中保持不变,那是错误的。事实上,即使在一个程序的同一次运行期间,具有自动存储持续时间的局部变量也可能在同一个运行实例中的多个调用中获得不同的地址。考虑:
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
这是因为当输入 foo
时,对 bar
的调用会在堆栈上创建另一个帧,从而为 a
提供不同的地址。一般来说,我认为唯一可以安全推理的是,如果变量具有静态存储持续时间,则其地址应该在 单次运行程序。
为什么多次运行你的程序会观察到不同的地址,那是因为:
- C 标准与 ABI、可执行文件格式和加载程序无关。
- Advances in security通常意味着您不应期望在现代操作系统上多次运行用户模式程序时看到相同的地址。
关于c - x86-64 中的内存分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54874903/