In my previous post “A Heap of Problems” I have compiled a list of problems the free store (heap) can cause in real-time embedded (RTE) systems. This was quite a litany, although I didn’t even touch the more subtle problems yet (for example, the C++ exception handling mechanism can cause memory leaks when a thrown exception bypasses memory de-allocation).
Far Reaching Implications of the Heap
But even though the free store is definitely not a free lunch, getting by without the heap is certainly easier said than done. In C, you will have to rethink implementations that use lists, trees, and other dynamic data structures. You’ll also have to severely limit your choice of the third-party libraries and legacy code you want to reuse (especially if you borrow code designed for the desktop). In C++, the implications are even more serious because the object-oriented nature of C++ applications results in much more intensive dynamic-memory use than in applications using procedural techniques. For example, most standard C++ libraries (e.g., STL, Boost, etc.) require the heap. Without it, C++ simply does not feel like the same language. Here are a few common sense guidelines for dealing with the heap:
Living Without the Heap
For smaller systems, such as microcontrollers with only on-chip RAM, you probably don’t want to open the heap can of worms at all. The problems and waste that come with the heap aren’t simply worth the trouble.
Living With the Heap
For systems with sufficient RAM, such as processors with megabytes of external DRAM, trading some of this cheap RAM for convenience in programming might be a reasonable deal. In the following discussion I assume that the system is big enough to run under a preemptive RTOS/GPOS.
The simplest option is to limit the use of the heap to just one task. In this case, heap is not being shared concurrently and does not need any mutual-exclusion protection mechanism. To limit the non-determinism of the heap, I would recommend assigning low priority to the task that uses the heap. The priority should be lower than any real-time task.
At the expense of introducing a mutual protection to all heap operations (e.g., a mutex), you can allow more than one task to use the heap. However, I would still strongly recommend against using the heap in any tasks with real-time deadlines. All tasks that use the heap should run at a lower priority than any of the real-time tasks.
In any case, heap should never be used inside the interrupt service routines (ISRs).
Don't Take It For Granted
In summary, using the heap in real-time embedded (RTE) systems always requires extra thought and discipline. You should not take the use of the heap for granted and instead carefully limit its use to where it makes sense. By this I mean that the benefits of using the heap should outweigh the problems it may cause. In any case, always make sure that the heap is correctly integrated with your runtime environment.