Understanding C Memory Layout on STM32: Stack, Heap, and Global Sections
This article explains the C language memory segmentation—including stack, heap, global/static, constant, and code areas—illustrates their behavior on STM32F103 with Keil V5, and provides detailed example code that prints the addresses of variables in each region to demonstrate allocation and lifetime.
C Language Memory Segments
The C runtime divides program memory into distinct regions, each with its own allocation rules and lifetime:
Stack : Automatically allocated and released by the compiler and operating system. Local variables, function parameters and return values reside here. Grows from high to low addresses, size fixed at link time, fast access.
Heap : Managed manually by the programmer with malloc and free. Grows from low to high addresses, size limited by available RAM/virtual memory, allocation is slower but flexible.
Global/Static Area : Stores global variables and static variables that persist for the entire program execution. Divided into .bss (uninitialized) and .data (initialized) segments.
Constant Area : Holds string literals, numeric constants and const -qualified global variables. Contents are read‑only at runtime.
Code Area : Contains the executable instructions of the program. Typically read‑only; modifying it results in undefined behavior.
STM32F103 Memory Allocation (Keil V5)
ROM (Read‑Only Memory) : Starts at 0x08000000, size 0x10000. Stores the code area and constant area.
RAM (Random‑Access Memory) : Starts at 0x20000000, size 0x5000. Holds the global/static area, heap and stack.
Verification Program on STM32
The following source demonstrates how variables from each memory region are declared and how their addresses are printed at runtime. The program runs an infinite loop, printing addresses of stack variables, heap allocations, global/static variables, constant strings, and the entry point of main. Heap allocations are freed each iteration to avoid memory leaks.
#include "main.h"
#include <string.h> // string handling
#include <stdio.h> // printf
#include <stdlib.h> // malloc, free
#include "delay.h"
#include "uart3.h"
#include "led.h"
// Global (uninitialized) variables – .bss
int q1; // uninitialized global
static int q2; // uninitialized static
const int q3; // uninitialized const (treated as .bss)
// Global (initialized) variables – .data
int m1 = 1; // initialized global
static int m2 = 2; // initialized static
// Constant area – .rodata
const int m3 = 3; // read‑only constant
int main(void) {
SystemCoreClockUpdate();
LED_GPIO_Config();
Uart3_init();
while (1) {
// ----- Stack variables -----
int mq1; // uninitialized local
int *mq2; // uninitialized pointer
int mq3 = 3; // initialized local
char qq[10] = "hello"; // initialized local array
const int mq4; // uninitialized const local
const int mq5 = 3; // initialized const local
// ----- Heap allocation -----
int *p1 = malloc(4);
int *p2 = malloc(4);
// ----- Static locals (global area) -----
static int mp1; // .bss static local
static int mp2 = 2; // .data static local
// ----- Constant area pointers -----
char *vv = "I LOVE YOU"; // string literal
char *mq = "5201314"; // another literal
// Print addresses
printf("
Stack area addresses:
");
printf("mq1 (uninit) : %p
", &mq1);
printf("mq2 (ptr) : %p
", &mq2);
printf("mq3 (init) : %p
", &mq3);
printf("qq (array) : %p
", qq);
printf("mq4 (const uninit) : %p
", &mq4);
printf("mq5 (const init) : %p
", &mq5);
printf("
Heap area addresses:
");
printf("p1 (int*) : %p
", p1);
printf("p2 (int*) : %p
", p2);
printf("
Global area addresses:
");
printf("q1 (uninit) : %p
", &q1);
printf("q2 (static uninit) : %p
", &q2);
printf("q3 (const uninit) : %p
", &q3);
printf("m1 (init) : %p
", &m1);
printf("m2 (static init) : %p
", &m2);
printf("mp1 (static local) : %p
", &mp1);
printf("mp2 (static local) : %p
", &mp2);
printf("
Constant area addresses:
");
printf("m3 (const init) : %p
", &m3);
printf("vv (string literal) : %p
", vv);
printf("mq (string literal) : %p
", mq);
printf("
Code area address:
");
printf("main function entry : %p
", main);
led485_flicker();
delay_ms(1000);
free(p1);
free(p2);
}
return 0;
}This program confirms the theoretical layout of memory segments on an STM32F103 by printing the actual runtime addresses of variables residing in each region.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
