简体   繁体   English

x86-64中的内存分配

[英]Allocation of memory in x86-64

I just want to make it clear to myself about memory allocation (if that's how I may call it correctly) in c on x64 architecture. 我只是想让我自己清楚x64架构上的c中的内存分配(如果我可以正确地称呼它)。

I have one program that simply outputs the location of the variable in the memory. 我有一个程序可以简单地输出变量在内存中的位置。 I run it several times and then I see some strange thing going on: 我运行了几次,然后发现发生了一些奇怪的事情:

The line of code: 代码行:

printf("[*] test_val @ 0x%016llx = %d 0x%016llx\n", &test_val, test_val, test_val);

1st time: 第一次:

[*] test_val @ 0x00005612f1edb050 = -72 0x00000000ffffffb8

2nd time: 第二次:

[*] test_val @ 0x000055ec3b64f050 = -72 0x00000000ffffffb8

3rd time: 第三次:

[*] test_val @ 0x00005577e99d4050 = -72 0x00000000ffffffb8

It seems that the memory location of the variable test_int is different every time except for the first 2.5 bits (00005) and the last 1.5 bits (the 050 part doesn't change). 似乎变量test_int的存储位置test_int都不同,除了前2.5位(00005)和后1.5位(050部分不变)之外。

There would've been no question, but in the book I'm learning by this address is constant all the time. 毫无疑问,但是在书中我所学到的这个地址一直都是不变的。 The main difference is that this book is about 32bit architecture. 主要区别在于本书是关于32位体系结构的。

Do I understand correctly that the memory is being allocated dynamicly in x64 systems? 我是否正确理解内存是在x64系统中动态分配的? Is there any way to "predict" where will the variable be, considering the fact that we know last 1.5 bits, 050 in this case? 考虑到我们知道最后1.5位(在这种情况下为050),有什么方法可以“预测”变量的位置?

There would've been no question, but in the book I'm learning by this address is constant all the time. 毫无疑问,但是在书中我所学到的这个地址一直都是不变的。

If this book actually claimed that addresses are to remain constant throughout multiple runs of the same program, it was wrong. 如果这本书实际上声称在同一程序的多次运行中地址将保持不变,那是错误的。 In fact, even during the same run of one program, local variables with automatic storage duration might get different addresses throughout multiple calls in the same running instance. 实际上,即使在一个程序的相同运行期间,具有自动存储持续时间的局部变量也可能在同一运行实例的多个调用中获得不同的地址。 Consider: 考虑:

void foo()
{
    volatile int a = 12345;
    printf("%p\n", (void *)&a);
}
void bar()
{
    printf("In bar\n");
    foo();
}
int main()
{
    foo();
    bar();
    return 0;
}

I get the output: 我得到的输出:

00B6FE58
In bar
00B6FE54

This is because the call to bar creates another frame on the stack when foo is entered, giving a a different address. 这是因为在输入foo时,对bar的调用会在堆栈上创建另一个框架,并a一个不同的地址。 In general, the only thing that is safe to reason about, I believe, is if a variable has static storage duration, its address should remain constant throughout a single run of a program. 通常,我认为,唯一可以合理推断的是,如果变量具有静态存储持续时间,则其地址在程序的一次运行中保持恒定。

As for why you're observing different addresses when running your program multiple times, that's because: 至于为什么多次运行程序时会观察到不同的地址,原因是:

  1. The C Standard is agnostic to ABIs, executable file formats, and loaders. C标准与ABI,可执行文件格式和加载器无关。
  2. Advances in security generally mean you shouldn't expect to see the same addresses throughout multiple runs of a user-mode program on a modern operating system. 安全性的提高通常意味着您不应期望在现代操作系统上的用户模式程序的多次运行中看到相同的地址。

You don't specify the operating system. 您没有指定操作系统。 However, it has become common for operating systems to load applications at random locations in memory. 但是,操作系统在内存中的随机位置加载应用程序已变得很普遍。 Compilers and linkers have produced relocatable code for decades but historically this was done to allow shared libraries to be loaded in different locations from different programs. 编译器和链接器已经产生了可重定位的代码数十年,但是从历史上看,这样做是为了允许将共享库从不同程序加载到不同位置。

Now operating systems are loading the program at different locations. 现在,操作系统正在不同位置加载程序。 This is done as a security measure. 这是一项安全措施。 The objective is to prevent crackers from manipulating specific memory locations. 目的是防止破解者操纵特定的内存位置。

The reason the last few bits of the address is the same is because the program is aligned on page boundaries. 地址的最后几位相同的原因是因为程序在页面边界上对齐。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM