如何在c函数中访问堆起始地址和堆基地址

Posted

技术标签:

【中文标题】如何在c函数中访问堆起始地址和堆基地址【英文标题】:How to access heap start address and heap base address within c function 【发布时间】:2020-01-02 15:54:31 【问题描述】:

对于我自己的malloc动态内存分配实现,我想在运行时访问堆基地址和堆限制地址。我知道它们在我的 startup.s 文件中被导出为全局变量。我怎样才能访问这些地址? 目标平台是带有 GCC 的 ARM Cortex-M4。

.globl 声明的符号对链接器来说是已知的,并且应该可以使用 c 代码中的 extern 符号访问。但是使用这种方法,我得到的值与生成的 .map 文件中的值不同。

下面是 startup.s 文件中定义的堆符号:

#ifdef __HEAP_SIZE
    .equ        Heap_Size, __HEAP_SIZE
#else
    .equ        Heap_Size, 0x00000C00
#endif
    .globl      __HeapBase
    .globl      __HeapLimit
__HeapBase:
    .if Heap_Size
    .space      Heap_Size
    .endif
    .size       __HeapBase, . - __HeapBase
__HeapLimit:
    .size       __HeapLimit, . - __HeapLimit

    .section    .vectors
    .align      2
    .globl      __Vectors

这是我在 c 函数中的访问权限:

extern volatile __HeapBase;
extern volatile __HeapLimit;

static void heaptest(void) 
    uint32_t limit;
    uint32_t base;

    base = __HeapBase;
    limit = __HeapLimit;

调试这段代码,我得到了生成的 .map 文件中指定的其他地址:

.heap           0x200317a0    0x40000
                0x200317a0                __HeapBase = .
...
                0x200717a0                __HeapLimit = .
...

所以我希望 __HeapBase 的输出为 0x200317a0__HeapLimit 的输出为 0x200717a0,但实际输出我得到的是 0xf377aaa20xac69254

【问题讨论】:

你是如何编译、链接和运行它的?添加所需的其余代码以获得minimal and reproducible example(强调reproducible)。 【参考方案1】:

将它们声明为 extern char __HeapBase[];,因为在 C 中,数组对象的名称转换为指针,而其他对象的名称被隐式取消引用。

也许还可以使用#define HEAPBASE ((void*)__HeapBase) 以方便使用该名称。或将其转换为 (uintptr_t) 或其他任何内容。

拥有一个单独的全局 void *base = &__HeapBase; 会不太好:base 不是编译时常数值,因为它甚至没有被声明为 const。使用它的代码必须从静态存储中加载一个指针,而不是拥有可以直接使用的链接时常量地址。

【讨论】:

【参考方案2】:

导出的符号是地址,但 C 编译器会为您取消引用它们。要取回地址,您需要应用地址运算符&,即void* base = &__HeapBase; 应该可以工作。正如所写,您实际上是从堆中获取第一项。

【讨论】:

以上是关于如何在c函数中访问堆起始地址和堆基地址的主要内容,如果未能解决你的问题,请参考以下文章

C++ - 从结束地址获取函数的起始地址/获取函数的大小

堆栈地址和堆地址之间的关系?

好友分配算法 - 起始堆地址

栈堆和拷贝

JavaScript基本语法

栈大小和堆大小