How to make sure no Dynamic Memory is used

In many embedded applications, it is mandatory that memory allocation is static and not dynamic. Means that no calls to things like malloc() or free() shall be used in the application, because they might fail at runtime (out of memory, heap fragmentation).

But when linking with 3rd party libraries or even with the C/C++ standard libraries, how to ensure no dynamic memory is used? The problem can occur as well for C++ objects, or a simple call to printf() which internally requires some dynamic memory allocated.

Zero Heap Size?

An easy (and rather naive) approach is to set the heap size to zero. Most linker script or linker environments have the ability to set the heap size to zero, as below:

However, this won’t help, as most linker scripts just uses the free space between the stack space and the variables (bss): So setting the heap size to zero just assumes a zero reservation, but the _sbrk() of the library will continue to use dynamic memory, potentially crashing into the stack space.

Bottom line: with most linker scripts heap size set to zero will not help anything. It even increases the chances that the heap will crash into the stack as the linker assumes zero usage of heap. But it won’t prevent that the heap is used.

Heap in Linker File

This can be seen from the linker file shown below:

To make sure that no heap is used, the easiest way is to simply remove the .heap allocation in above linker file. Check your linker file for ‘heap’ or something similar, and make sure no memory is allocated for it. Especially make sure that no symbol ‘__prvHeapStart‘ or ‘__prvHeapLimit‘ is used, as they usually are required by the newlib/newlib-nano library dynamic memory allocation.

Linker FreeMarker Scripts

Some environments like the NXP MCUXpresso IDE is using an automatic generation of linker files. But it is easy to deal with this, if you know about the FreeMarker Scripts used by this. The Scripts are located in

<MCUXpresso IDE Installation Path>\ide\Wizards\linker

So I can easily disable the .heap using my modified FreeMarker Script:

__sbrk()

With the heap and its symbols removed, any usage of malloc() should give a linker error, similar to this one:

Invoking: MCU Linker
arm-none-eabi-gcc -nostdlib -Xlinker -Map="AEMBS_tinyK22_HS22.map" -Xlinker --gc-sections -Xlinker -print-memory-usage -Xlinker --sort-section=alignment -Xlinker --cref -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -T "AEMBS_tinyK22_HS22_Debug.ld" -o "AEMBS_tinyK22_HS22.axf" ./utilities/fsl_assert.o ...  ./McuLib/FreeRTOS/FreeRTOShooks.o   
arm-none-eabi/bin/ld.exe: arm-none-eabi/lib/thumb/v7e-m+fp/hard\libcr_newlib_semihost.a(_cr_sbrk.o): in function `_sbrk':
_cr_sbrk.c:(.text._sbrk+0x38): undefined reference to `_pvHeapStart'

Good!

Linker Cross Reference

In case it is not clear what is using memory allocation or causing the error, the linker cross reference can be used. For this the GNU linker –cref option has to be added to the linker options:

This generates an information like below in the linker .map file:

Cross Reference Table

Symbol                                            File
ADC0_DriverIRQHandler                             ./startup/startup_mk22f51212.o
ADC0_IRQHandler                                   ./startup/startup_mk22f51212.o
ADC16_ClearStatusFlags                            ./drivers/fsl_adc16.o
ADC16_Deinit                                      ./drivers/fsl_adc16.o
...
main                                              ./source/main.o
                                                  ./startup/startup_mk22f51212.o
malloc                                            arm-none-eabi/lib/thumb/v7e-m+fp/hard\libc_nano.a(lib_a-malloc.o)
                                                  arm-none-eabi/lib/thumb/v7e-m+fp/hard\libc_nano.a(lib_a-rand.o)
                                                  ./drivers/fsl_common.o
mcgConfig_BOARD_BootClockRUN                      ./board/clock_config.o

This gives a list of modules which are using things like malloc().

Image Information

Another way to find out the dependencies is using the ‘Image Information’ view in Eclipse/MCUXpresso, see Listing Code and Data Size for all Files with the GNU size Utility in a Post-Build Action:

FreeRTOS static memory allocation

More on a side-note: FreeRTOS by default is using its own dynamic heap allocation. But it is possible to run the RTOS in a static way (no dynamic memory allocation), see FreeRTOS V9.0.0 with Static Memory Allocation.

Summary

Dynamic memory allocation and usage is not desired in many applications. To prevent usage of malloc() and free(), it is best to remove any heap definition in the linker file, to cause a linker error. Then the GNU linker cross reference table or the image information can be very useful.

Happy linking 🙂

Links

8 thoughts on “How to make sure no Dynamic Memory is used

  1. I much prefer creating __wrap functions like malloc and free and then using a partition/block memory manager. Not allowing malloc and free creates extra work when working with third party libraries and code.

    Liked by 1 person

    • Sure, that’s an approach too. But would pretty much undermine the goal of not using a dynamic memory manager. But it all depends on the application, of course: using your own manager might reduce the problem of memory fragmentation. But it won’t remove the problem possibly not meeting your real-time requirements because the time for allocation or freeing memory is not consistent. Beside of the usual programming errors (double free, memory leaks) this is the main reason why using dynamic memory allocation is not used for any system which shall be reliable (which I assume every system should be?).

      Like

      • Define reliable and real time? Do you consider a cellphone or satellite modem reliable or real time? Are you talking medical devices, aviation, space, etc. with zero room for failure and at time extreme power requirements? What RTOS providers are you going to recommend that does not require a heap and memory management? I recognize your goal, but I do not see a problem statement it solves with real world examples which are needed to to justify the long term effort of removing the heap.

        Liked by 1 person

        • ‘Reliability’ has many aspects, and I consider it as the concern about a system to perform its required function under stated conditions for a defined time.
          And ‘real-time’ as the concern about a system to perform its duties correctly and under the given timing conditions. Each of your mentioned systems (cellphone, satellite modem) has concerns in each domain, with different requirements, so do the other areas you mention (aviation, medical, …) where usually there is a distinction between ‘hard’ and ‘soft’ real-time, with the criteria if some failures are acceptable or not.
          As for the RTOS to be used: this again depends on the requirements and domain you want to use it in, for example if it requires certification or not, or if you want to make your own certification. As for FreeRTOS: it had originally the concept of ‘dynamic heap’, where the RTOS allocates its structures (stack for tasks, internal data structures) on its own dynamic heap. Because of the requirements of certain industries (like medical, aviation) not to use any dynamic allocation, Richard Barry added the feature of a ‘static’ RTOS, means that all previously dynamic parts can be defined as static memory areas.
          The main motivation of not using a dynamic heap is to have a more predictable execution time to meet the real-time requirements, because typical heap implementation maintain a list of memory blocks, and the length of this list affects the execution time, making it difficult to ‘prove’ the real-time requirements met. The other aspect is that depending on the order and usage of the heap, it is subject to memory fragmentation leading possibly to an ‘out-of-memory’ situation.

          Like

What do you think?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.