堆让我很困扰,因为我不明白是谁创建它,谁维护它以及谁决定它应该放在哪里......这个测试显示了我的部分难题:
源代码:
#include <malloc.h>
#include <stdio.h>
int a;
int b = 5;
int * getMeAPointer() {
int * e = malloc(4);
*e = 5;
return e;
}
void main() {
a = 5;
int c = 5;
int * d = (int *) 0x405554;
*d = 5;
int * e = getMeAPointer();
printf("Address of a located in .bss is %x\n", &a);
printf("Address of b located in .data is %x\n", &b);
printf("Address of c located in stack is %x\n", &c);
printf("Address of d located in stack is %x\n", &d);
printf("Address of *d located absolutely is %x\n", d);
printf("Address of e located in stack is %x\n", &e);
printf("Address of *e located on heap is %x\n", e);
printf("Address of getMeAPointer() located in .text is %x\n", getMeAPointer);
free(e);
}
示例打印输出:
Address of a located in .bss is 0x405068
Address of b located in .data is 0x402000
Address of c located in stack is 0x22ff1c
Address of d located in stack is 0x22ff18
Address of *d located absolutely is 0x405554
Address of e located in stack is 0x22ff14
Address of *e located on heap is 0x541738
Address of getMeAPointer() located in .text is 0x4013b0
Address of a located in .bss is 0x405068
Address of b located in .data is 0x402000
Address of c located in stack is 0x22ff1c
Address of d located in stack is 0x22ff18
Address of *d located absolutely is 0x405554
Address of e located in stack is 0x22ff14
Address of *e located on heap is 0x3a1738
Address of getMeAPointer() located in .text is 0x4013b0
Address of a located in .bss is 0x405068
Address of b located in .data is 0x402000
Address of c located in stack is 0x22ff1c
Address of d located in stack is 0x22ff18
Address of *d located absolutely is 0x405554
Address of e located in stack is 0x22ff14
Address of *e located on heap is 0x351738
Address of getMeAPointer() located in .text is 0x4013b0
....etc....
现在这些是我的担忧:
为什么堆在移动而其他段都没有?这是在带有 MinGW 的 Windows 7 操作系统上,此文件是使用 GCC 编译的,没有进一步的标志(我不认为这是地址空间布局随机化的示例)。
谁决定堆应该放在哪里?我相信链接器为堆保留了一个位置(我在符号表中看到过堆符号)但是什么时候确定确切的地址,它是由 RUNNABLE 本身(C 代码)在加载后完成的运行时事情,还是它由链接器/加载器/动态链接器在执行前加载程序时完成?
有没有办法在ld中设置堆地址?我知道我可以设置除堆栈之外的所有段(因为它内置在操作系统的内核中)但是我可以设置堆地址吗?
按照我的理解,堆并不是真正的汇编语言构造,如果我们选择只进行汇编编程,我们将无法访问堆。因此它是一个 C 构造,但我感兴趣的是它如何影响堆的生命周期(我的意思是我们说堆就像它与段和堆栈处于同一级别但如果不是,那么应该给它很多其他条件)...这是正确的吗?谁能告诉我更多关于它的信息?
老实说,我已经谷歌了一整天,我渴望得到一些答案!
最佳答案
Why is the heap moving around and none of the other segments?
因为动态内存分配是动态的。您从malloc()
返回的地址取决于可以找到足够大的空闲内存块的位置< strong>在您的程序正在执行的那一刻。显然,由于还有其他程序,这会随着时间而改变。
Who decides where the heap should be?
您的操作系统的开发者。
I belive [sic!] the linker reserves a place for the heap
很少。在我见过的大多数实现中,这完全是运行时的事情。 (不是说链接器不可能有关系,但还是有关系。)
Is there any way to set the heap address in ld?
如果有,肯定是documented . (假设您所指的 ld
是工具链中的链接器。)
[...] I can set all segments except stack (since that's built into the kernel of the OS)
我不认为我完全理解你在说什么,但是“堆栈”并不是“内置于内核中”。通常,堆栈地址要么静态硬编码到可执行文件中,要么使用相关指令引用。
the heap is not really an assembly language construct and we don't have access to a heap if we choose to just do assembly programming.
但是是的,你知道。我不熟悉 Windows,但在大多数 Unix 上,您可以使用 brk()
和/或 sbrk()
系统调用。
Therefore it is a C construct
你的逻辑有问题。仅仅因为某些东西不是汇编的东西,它不会自动意味着它是 C 的东西。事实上,C语言中并没有所谓的“堆”或“栈”。C语言中只有自动、静态和动态的存储时长,与具体的实现方式无关。
关于C 堆地址在运行之间发生变化,而其他地址仍然存在,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22275305/