On platforms with tightly restricted data memory and without virtual memory management, it is cruical to handle memory deterministically from within the embedded software application. Allocating and freeing memory dynamically on the heap during runtime without close control ist very dangerous:
- Even if all dynamically allocated memory is properly released when it is no longer needed, the system may run out of heap memory due to heap fragmentation.
- Another reason why dynamic memory allocation can cause headaches is the fact that the allocation operation may not be deterministic.
This is why the following concept can be found very often in embedded software applications:
- allocate all required memory during the initialization phase
- do not allocate any dynamic memory during normal operation (i. e. after initialization)
- operate on memory pools, when instances need to be dynamically created and destroyed during normal operation
The redBlocks Memory Managment Components provide classes that support this concept.
The HeapManager keeps track of deterministic memory allocation and provides various housekeeping information needed by the software developers (e. g. used heap size).
It replaces the standard library's new operator with an implementation that requires less administrative information and always works deterministic. It supports the concept that all heap memory that is needed by the various parts of the embedded software is allocated during the initialization phase. After the initialization is done, further dynamic memory allocation is prohibited.
As even rather trivial embedded software applications need to dynamically create and destroy objects (e. g. message objects that are passed through the system), the redBlocks Memory Components include a very convenient implementation of memory pools.
The following code snippets show how easy it is to associate a class SomePooledClass with a memory pool:
The class is made a pooled class by deriving from the redBlocks class TPooledBase:
class SomePooledClass : public redBlocks::Memory::Pool::TPooledBase<SomePooledClass>
During system startup, sufficient memory for the associated pool must be allocated from the heap, in order to be able to create as many instances of the pooled class as later (after the startup phase) needed. The following line of code allocates enough pool memory for five instances of the pooled class from the heap:
As this call dynamically allocates memory from the heap, it must not be executed after the initialization phase. However, as the required memory for instantiating the pooled class is taken from the preallocated pool memory, instances of a pooled class can be dynamically created and destroyed during runtime without any risk of memory fragmentation. For creating and deleting instances of a pooled class, the standard C++ operators new and delete can be used:
SomePooledClass* instance = new SomePooledClass();
As the pooled classes are dynamically created and destroyed with the standard operators, they can easily be used in conjunction with smart pointers (e. g. STL's unique_ptr).
Defining the right stack sizes is an important task in embedded software applications. Overprovisioning the stack, wastes memory that could be used for other purposes. When underprovisioning the stack, the system is prone to stack overflow.
With the redBlocks Stack Manager, it is easy to measure the stack usage of the embedded software application. It can be easily included in your embedded software application and determines the actually used size of the configured stack.