x86-64 中的内存分配
Allocation of memory in x86-64
我只是想让自己清楚地了解 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,有什么方法可以 "predict" 变量在哪里?
There would've been no question, but in the book I'm learning by this address is constant all the time.
如果这本书实际上声称地址在同一程序的多个运行中保持不变,那是错误的。事实上,即使在一个程序的同一个 运行 中,具有自动存储持续时间的局部变量也可能在 same 运行ning 实例中的多个调用中获得不同的地址。考虑:
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
提供不同的地址。一般来说,我认为唯一可以安全推理的是,如果一个变量具有静态存储持续时间,它的地址 应该 在整个 单个 运行一个程序。
至于为什么多次 运行ning 程序时会观察到不同的地址,那是因为:
- C 标准与 ABI、可执行文件格式和加载程序无关。
- Advances in security 通常意味着您不应期望在现代操作系统上的用户模式程序的多个 运行 中看到相同的地址。
您没有指定操作系统。然而,操作系统在内存中的随机位置加载应用程序已经变得很普遍。编译器和链接器几十年来一直在生成可重定位代码,但从历史上看,这样做是为了允许共享库从不同程序加载到不同位置。
现在操作系统正在不同的位置加载程序。这是一项安全措施。 objective 是为了防止破解者操纵特定的内存位置。
地址的最后几位相同的原因是程序在页边界上对齐。
我只是想让自己清楚地了解 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,有什么方法可以 "predict" 变量在哪里?
There would've been no question, but in the book I'm learning by this address is constant all the time.
如果这本书实际上声称地址在同一程序的多个运行中保持不变,那是错误的。事实上,即使在一个程序的同一个 运行 中,具有自动存储持续时间的局部变量也可能在 same 运行ning 实例中的多个调用中获得不同的地址。考虑:
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
提供不同的地址。一般来说,我认为唯一可以安全推理的是,如果一个变量具有静态存储持续时间,它的地址 应该 在整个 单个 运行一个程序。
至于为什么多次 运行ning 程序时会观察到不同的地址,那是因为:
- C 标准与 ABI、可执行文件格式和加载程序无关。
- Advances in security 通常意味着您不应期望在现代操作系统上的用户模式程序的多个 运行 中看到相同的地址。
您没有指定操作系统。然而,操作系统在内存中的随机位置加载应用程序已经变得很普遍。编译器和链接器几十年来一直在生成可重定位代码,但从历史上看,这样做是为了允许共享库从不同程序加载到不同位置。
现在操作系统正在不同的位置加载程序。这是一项安全措施。 objective 是为了防止破解者操纵特定的内存位置。
地址的最后几位相同的原因是程序在页边界上对齐。