如何在c函数中访问堆起始地址和堆基地址
How to access heap start address and heap base address within c function
我自己的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 = .
...
所以我希望 0x200317a0 对于 __HeapBase 和 0x200717a0 ] 对于 __HeapLimit,但我得到的实际输出是 0xf377aaa2 和 0xac69254.
导出的符号是地址,但 C 编译器会为您取消引用它们。要取回地址,您需要应用寻址运算符 &
,即 void* base = &__HeapBase;
应该有效。正如所写,您实际上是从堆中获取第一项。
将它们声明为extern char __HeapBase[];
,因为在 C 中,数组对象的名称转换为指针,而其他对象的名称被隐式取消引用。
或许也可以用#define HEAPBASE ((void*)__HeapBase)
方便起名。或者将其转换为 (uintptr_t)
或其他。
有一个单独的全局 void *base = &__HeapBase;
会不太好:base
不是编译时常量值,因为它甚至没有声明为 const
。使用它的代码必须从静态存储中加载一个指针,而不是直接使用 link 时间常量地址。
我自己的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 = .
...
所以我希望 0x200317a0 对于 __HeapBase 和 0x200717a0 ] 对于 __HeapLimit,但我得到的实际输出是 0xf377aaa2 和 0xac69254.
导出的符号是地址,但 C 编译器会为您取消引用它们。要取回地址,您需要应用寻址运算符 &
,即 void* base = &__HeapBase;
应该有效。正如所写,您实际上是从堆中获取第一项。
将它们声明为extern char __HeapBase[];
,因为在 C 中,数组对象的名称转换为指针,而其他对象的名称被隐式取消引用。
或许也可以用#define HEAPBASE ((void*)__HeapBase)
方便起名。或者将其转换为 (uintptr_t)
或其他。
有一个单独的全局 void *base = &__HeapBase;
会不太好:base
不是编译时常量值,因为它甚至没有声明为 const
。使用它的代码必须从静态存储中加载一个指针,而不是直接使用 link 时间常量地址。