Overview
A typical memory representation of a C language program consists of following segments:
- Code (Text) segment – contains the program code (machine instructions)
- Data segment – contains the static data (global/static variables)
- Stack segment (see our article on the topic The Concept of Stack and Its Usage in Microprocessors)
- Heap segment

Fig.1 Memory Segments
In systems where an Operating System is present the address space for the heap and the stack can be dynamically changed (managed). This is in contrast to the small embedded systems where the address space for both the heap and the stack is known at compilation time. A distinction should be made between the dedicated address space and the current segment size of both the heap and the stack. The current segment size of both is dynamically changing (grows or shrinks) during program execution.
A common misconception is that that the heap grows upwards (starting after the data segment) and the stack grows downwards. These are platform/architecture dependent specifics. The C language for example does not specify the minimum size or the location of the heap and the stack in the memory.
Heap and Dynamic Memory Allocation
The heap is a segment of the system memory (RAM) that provides dynamic memory allocation.
There are two types of memory allocation:
- Static allocation (in the data segment):
- Memory for named variables is allocated at compile time
- Exact size and type of storage is known at compile time
- Dynamic allocation (in the heap segment):
- Memory allocated during program execution
- Exact amount of space does not have to be known at compile time
Dynamic allocation usually requires two basic steps:
- Creating the dynamic space
- Creating a pointer holding the address for the newly created space (new variable names can’t be created while the program is running, so pointers are needed)
Although, C language inherently does not have any technique to allocate memory dynamically, there are several functions (part of stdlib library) for dynamic memory allocation and management:
- malloc() and calloc( ) – reserve space
- realloc() – move a reserved block of memory to another allocation of different dimensions
- free() – release allocated space
Heap Usage
Here are some of the most common cases when the heap is used:
- When we need a data that must live after the function returns. Once data is stored on the heap during function execution it is not affected when the function ends
- When we need a lot of memory
- When we don’t know exactly how much data we will need to store during the execution of the program
Heap Usage Pitfalls
Using dynamic memory allocation brings a certain degree of complexity and if the end application does not explicitly requires it, the usage of heap should be avoided (especially in small embedded systems). There are a lot of specifics that a person should be familiar with before deciding on using the heap. Below are listed some common pitfalls, when the heap integrity is compromised:
- Overwritten heap data
- Allocation failures, when a too big buffer is requested to be allocated.
- Heap is responsible for memory leaks
- The C malloc() and free() function can take a long time to execute, which is in conflict with the real-time constraints of an embedded system
- Heap memory management requires additional memory as the algorithms need to store some form of header information for each allocated block
Hi Yasen,
Great article. Im trying to understand these concepts and was wondering why the .bss is not mentioned here. In another article you provide it is explained as the memory area for uninitialized variables. So from there I thought that we had: .data , .text, .bss, heap and stack.
Could you clarify this? Thanks for the help :)
this is the article i refer to: https://open4tech.com/memory-layout-embedded-c-programs/
Hello Alexsan91,
The .bss (Uninitialized Data Segment) is not explicitly mentioned in this article as it has no direct relation to the heap. The .bss and the .data segments form the Data Segment shown in Fig.1 Memory Segments. I think that your understanding is correct. The common segments of the memory layout are:
– Code segment (.text);
– Initialized data segment (.data) and Uninitialized data segment (.bss) both forming the Data segment;
– Heap;
– Stack.
I hope this clarifies the confusion, if not please don’t hesitate to ask further questions :)