cmemorydynamicmisra

Are memory pools MISRA C Dir 4.12 compliant?


Following How do I create a module in MISRAC:2012 that follows Dir 4.12 and 4.8? discussion. I fail to see how memory pools are MISRA C Dir 4.12 compliant.

If we read the directive 4.12 it is said that dynamic memory usage shall not be used to avoid undefined behavior as specified in rule 21.3 that enumerates the following failure modes, amongst other, as examples:

Later on, directive 4.12 says that "If a decision is made to use dynamic memory" (and I read here "deviation") "care shall be taken that ensures software behaves in a predictable manner".

In the mentioned previous thread, @Lundin answer completly ignores the undefined behavior risk and just focuses on the deterministic behavior of a memory pool implementation compared to a malloc/free implementation, which it seems to me is the deviation path, no the rule itself. The rule, as it is written, it is said to prevent bad application usage of dynamically allocated/freed memory by the application leading to undefined behavior.

Finally, even if the stack is dynamic, the protocol to access it is totally controlled by the compiler, so I would say it cannot be compared to memory pools or any othe dynamic memory allocation mechanism in terms of reliability.

It looks to me that MISRA C rationale on Dir 4.12 warns about the risk of the dynamic memory protocol itself to lend to undefined behavior when accessing memory. Confusingly enough, then it says that if you decide to use dynamic memory you should be aware of the deterministic behavior of allocations, which is another orthogonal matter.

MISRA C mixes, for example, "accessing to a freed pointer" (the problem said to be prevented) with deterministic behavior of allocation/deallocation (the other problem said to prevent if you use dynamic memory).

My interpretation is that if you want your software to be realiable you should control both. So maybe the most appropiate would be to:

  1. Evaluate if dynamic memory is really needed
  2. If so, deviate the rule and stablish controls to prevent both: application access errors and undeterministic allocation/deallocation behavior.

Solution

  • First of all, we have to realize that MISRA-C, being a technical document meant to be read by C programmers, places the same technical meaning into dynamic allocation as the C language does. It refers to data with allocated storage duration as defined by ISO C, or if you will allocation using "the heap" or "the freestore". So dynamic allocation doesn't just mean "some arbitrary memory that changes allocated size in run-time" (like for example the stack also does).

    Second, we have to realize that MISRA C didn't come up with this ban alone but also inherited it from standards for functional safety (IEC 61508 and ISO 26262), standards for aviation software (DO-178 and the Joint Strike Fighter standards) and so on. All of which ban dynamic allocation.

    The MISRA C directive just mentions a few of the problems related to dynamic allocation and not the biggest ones either. Overall the MISRA C document isn't very good or consistent with listing rationales and sources. In this specific case I don't think they even bothered to flesh out the document's rationale, since there are many more problematic things not mentioned.

    I have written a more detailed and complete explanation of all the problems associated with these functions: Why should I not use dynamic memory allocation in embedded systems? Note that this is not just aimed to safety-related embedded systems but to all embedded systems.

    The major arguments in that list isn't really the "dynamicness" nor the usual problems related to "dangling pointers" and memory leaks. The major arguments against it from that linked post is that it is slow, it is memory consuming, it is bloat and all for no good reason. All in all 13 solid arguments why it shouldn't be used and 0 arguments why it should be used.

    In terms of undefined behavior specifically, apart what was already mentioned by MISRA, my post also addresses a few aspects not mentioned: indeterminate values and the effective type system, each which have lots of controversy, ISO C Defect Reports and generally poorly-specified behavior. In addition, my post also mentions the bad API of the standard C functions - malloc/realloc come with several very well-known bugs.

    I really doubt that anyone with a bit of understanding how heap allocation works 1) in general 2) on a microcontroller, can ever "evaluate if dynamic memory is really needed" and come to any other conclusion than that using it on a (bare metal/RTOS) microcontroller system is senseless.

    As for using statically allocated memory pools, they dodge pretty much all of the mentioned problems. Sure, they can also run into problems with effective type/strict aliasing just like malloc but that is about it. The advantage of rolling out your own static pool is that it's simple: it barely has any overhead, it gives as easy overview of how much memory that is allocated at any point in time, it doesn't fragment, it is contiguous and cache-friendly.

    The question you link to is specifically about how to allocate opaque types (encouraged by MISRA Dir 4.8), as the OP there says "I am looking for guidance on Dir 4.8", in a MISRA-compliant system. So that's what my answer focused on, not about the MISRA UB rationale for Dir 4.12. An answer for how to implement such memory pools/opaque type allocators in practice can be found here.