Keil环境下无法获取__heap_base地址,求堆基址正确存储方法
Let's break down why you're getting 0x00000000 for __heap_base and fix this step by step:
The core problem here is that you're treating __heap_base as a uint32_t variable, but it's actually a linker symbol—a marker for a memory address, not a variable with a stored value. Your compiler is looking for a variable named __heap_base that doesn't exist, so it defaults to a null pointer. Here's how to fix it:
1. Correct the C Declaration of __heap_base
Instead of declaring it as a uint32_t, treat it as an external void symbol (we only care about its memory address, not any value it might "hold"):
#include <stdint.h> // Declare __heap_base as an external linker symbol (not a variable) extern void __heap_base; // Directly take the symbol's address as the heap base void* original_heap_base = &__heap_base; void* mem_init() { void *temp = original_heap_base; original_heap_base += 4; return temp; } int main() { int *p = (int*)mem_init(); *p = 5; return 0; }
If you prefer using a uint32_t to store the address value, you can declare it as an array (this tricks the compiler into treating the symbol as a memory address marker):
extern uint32_t __heap_base[]; void* original_heap_base = (void*)__heap_base;
2. Verify Your Keil Scatter Loading Script (.sct)
Make sure your scatter script correctly defines and exports __heap_base at the start of your heap region. Here's a typical working example:
LR_IROM1 0x08000000 0x00040000 { ; Load region (Flash) ER_IROM1 0x08000000 0x00040000 { ; Execution region (Flash) *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM1 0x20000000 0x00010000 { ; RW data region (RAM) .ANY (+RW +ZI) } HEAP 0x20001000 0x00010000 { ; Heap region (adjust address/size to your MCU) __heap_base = .; ; Mark the exact start of the heap .ANY (+ZI) ; Optional: Include zero-initialized data here } }
Key checks:
__heap_base = .;must sit at the very start of your HEAP region to mark its base address.- The HEAP region's start address (e.g.,
0x20001000) must be a valid, unused RAM address for your hardware.
3. Force the Linker to Keep the __heap_base Symbol
Keil's linker might optimize away symbols it thinks are unused. To prevent this:
- Open your project's Options for Target.
- Navigate to the Linker tab.
- In the Misc Controls field, add:
--keep __heap_base
This ensures the linker retains the __heap_base symbol in the final executable.
4. Debug to Confirm the Address
After making these changes, use Keil's debugger to check the value of original_heap_base—it should match the HEAP start address you defined in your scatter script (e.g., 0x20001000). If it does, your custom memory management functions can safely use this address.
Quick Note on Heap Writes
When you run *p = 5;, double-check that your heap region doesn't overlap with other RAM areas like the stack or global variables. Your scatter script should clearly separate these regions to avoid memory corruption.
内容的提问来源于stack exchange,提问作者Abishek0398

