A typical memory representation of a C language program consists of following segments:

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:

  1. Creating the dynamic space
  2. 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

Was this article helpful?