C 堆地址在运行之间发生变化,而其他地址仍然存在

标签 c assembly linker heap-memory memory-address

堆让我很困扰,因为我不明白是谁创建它,谁维护它以及谁决定它应该放在哪里......这个测试显示了我的部分难题:

源代码:

#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....

现在这些是我的担忧:

  1. 为什么堆在移动而其他段都没有?这是在带有 MinGW 的 Windows 7 操作系统上,此文件是使用 GCC 编译的,没有进一步的标志(我不认为这是地址空间布局随机化的示例)。

  2. 谁决定堆应该放在哪里?我相信链接器为堆保留了一个位置(我在符号表中看到过堆符号)但是什么时候确定确切的地址,它是由 RUNNABLE 本身(C 代码)在加载后完成的运行时事情,还是它由链接器/加载器/动态链接器在执行前加载程序时完成?

  3. 有没有办法在ld中设置堆地址?我知道我可以设置除堆栈之外的所有段(因为它内置在操作系统的内核中)但是我可以设置堆地址吗?

  4. 按照我的理解,堆并不是真正的汇编语言构造,如果我们选择只进行汇编编程,我们将无法访问堆。因此它是一个 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/

相关文章:

android - 在 Android 中调用 OpenCL 函数时 undefined reference

c - 禁用默认警告的警告/错误

c - 如何在 C 中将 char 指针转换为 float?

assembly - x86 汇编中寄存器上使用的入栈/出栈指令的功能是什么?

c - "Art of Exploitation"反汇编例子不一样(C代码)

c++ - 链接器无法在库中找到符号

c++ - 如何通过 GNU Autotools 链接共享库

c - 关于用c解密图像文件的许多疑问

c - 显示结构

c++ - 逻辑/算术移位越少位越快吗?