【问题标题】:C heap address changes between runs while other addresses persistC 堆地址在运行之间更改,而其他地址保持不变
【发布时间】:2014-04-12 02:07:43
【问题描述】:

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

源代码:

#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 构造,但我对它如何影响堆的生命感兴趣(我的意思是我们说堆就像它与段和堆栈处于同一级别,但如果不是,那么应该给它很多其他条件)...这是正确的,谁能告诉我更多关于它的信息?

老实说,我整天都在谷歌上搜索,我渴望得到一些答案!

【问题讨论】:

  • 您的示例打印输出几乎相等...
  • no.. 看看堆中的 e 指向的是什么......这就是我整个问题的重点......
  • 哦,是的,没错。实际上,这是这里唯一有趣的地方。

标签: c assembly linker heap-memory memory-address


【解决方案1】:

为什么堆在移动而其他段没有移动?

因为动态内存分配是,嗯,动态的。你从malloc()返回的地址取决于在哪里可以找到足够大的空闲内存块你的那一刻程序正在执行中。显然,由于还有其他程序,因此会随着时间而改变。

谁决定堆的位置?

您的操作系统的开发人员。

我相信 [原文如此!] 链接器为堆保留了一个位置

很少。在我见过的大多数实现中,这完全是运行时的事情。 (不是链接器不可能与它有关,但仍然。)

有没有办法在ld中设置堆地址?

如果有,肯定是documented。 (假设您所指的ld 是您工具链中的链接器。)

[...] 我可以设置除堆栈之外的所有段(因为它内置在操作系统的内核中)

我不认为我完全理解你在说什么,但“堆栈”不是“内置于内核中的”。通常,堆栈地址要么被静态硬编码到可执行文件中,要么使用相关指令引用。

堆并不是真正的汇编语言结构,如果我们选择只进行汇编编程,我们就无法访问堆。

但是是的,你知道。我不熟悉 Windows,但在大多数 Unix 上,您可以使用 brk() 和/或 sbrk() 系统调用。

因此它是一个 C 构造

你的逻辑有问题。仅仅因为某些东西不是汇编的东西,它确实不是自动意味着它是一个 C 的东西。事实上,C 中并没有“堆”或“栈”之类的东西。在 C 中,只有自动、静态和动态的存储时长,与具体的实现方式无关。

【讨论】:

  • 感谢您的回答!好的,那么我认为可运行文件中的 C 代码正在通过 malloc() 获取空间,这是一个 C 构造。但是,您说还有其他程序,但这无关紧要,因为每个进程都有自己的虚拟环境(在我的系统中)。您是说操作系统更喜欢为堆使用物理地址而不是虚拟地址,因此它们在运行之间会发生变化?
  • @fast-reflexes 不。我只是说未指定的行为是未指定的行为。
  • 好的..但是我想知道这个过程......那么堆是操作系统的东西吗?由于操作系统正在返回空间?如果我在嵌入式系统中仅通过汇编编写一个小程序,则不会有堆,但会有堆栈和其他段。这就是我所说的堆不是汇编构造的意思...
  • 对于Windows的情况,你有GetProcessHeap()(甚至HeapCreate())、HeapAlloc()HeapFree()等。至少在MSVC中,C运行时库堆只是一个非常围绕操作系统堆的瘦包装器。
  • @fast-reflexes 是的,这是操作系统的事情。不,嵌入式与它是否可用无关。
【解决方案2】:

多种因素会影响堆的驻留位置,即

  • 应用程序的基地址
  • 应用程序所需的库
  • 操作系统分配给应用程序的内容

C 堆(简化)只是一个巨大的内存块,由应用程序的运行时维护,因此调用 malloc() 时获得的有效地址由该运行时定义。编译器版本和不同供应商之间的运行时不同。运行时用作堆的整个内存块是在应用程序启动时从操作系统获得的。在这里,操作系统可能会在每次运行应用程序时返回不同的地址。因此,堆地址是不可预测的。如果您的应用程序在运行期间开始分配和释放内存,它甚至会变得“更多”随机,因为现在运行时需要在当前分配的块之间找到空闲块等等。因此,除非运行之间的分配/解除分配顺序完全相同,否则即使堆基地址相同,您也会得到完全不同的地址。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-21
    • 2018-07-07
    • 2021-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多