Rule A18-5-5 (required, toolchain, partially automated)
Memory management functions shall ensure the following: (a) deterministic behavior resulting with the existence of worst-case execution time, (b) avoiding memory fragmentation, (c) avoid running out of memory, (d)
avoiding mismatched allocations or deallocations, (e) no dependence on non-deterministic calls to kernel.
Rationale
Memory management errors occur commonly and they can affect application stability and correctness. The main problems of dynamic memory management are as following: Non deterministic worst-case execution time of allocation and deallocation Invalid memory access Mismatched allocations and deallocations Memory fragmentation Running out of memory Custom memory management functions (custom allocators) need to address all of this problems for the project and all libraries used in the project. To ensure the worst-case execution time, the memory management functions need to be executed without context switch and without syscalls. To prevent running out of memory, an executable is supposed to define its maximal memory needs, which are pre-allocated for this executable during its startup. Memory management functions include operators new and delete, as well as lowlevel functions malloc and free. Nevertheless code written in C++ language uses new and delete operators, and direct use of malloc and free operations do not occur, some libraries, e.g. exception handling mechanism routines of libgcc uses malloc and free functions directly and omits new and delete operators usage. Custom memory management functionality needs to provide custom implementation of C++ new and delete operators, as well as implementation of malloc and free operations to hide incorrect dynamic memory allocation/deallocation in linked libraries. Note: If custom memory management requires to use custom std::new_handler, its implementation shall perform one of the following: make more storage available for allocation and then return throw an exception of type bad_alloc or a class derived from bad_alloc terminate execution of the program without returning to the caller
Example
//% $Id: A18-5-5.cpp 289815 2017-10-06 11:19:11Z michal.szczepankiewicz $
#define __GNU_SOURCE
#include <dlfcn.h>
#include <cstddef>
void* MallocBad(size_t size) // Non-compliant, malloc from libc does not
// guarantee deterministic execution time
{
void* (*libcMalloc)(size_t) = (void* (*)(size_t))dlsym(RTLD_NEXT, "malloc");
return libcMalloc(size);
}
void FreeBad(void* ptr) // Non-compliant, malloc from libc does not guarantee
// deterministic execution time
{
void (*libcFree)(void*) = (void (*)(void*))dlsym(RTLD_NEXT, "free");
libcFree(ptr);
}
void* MallocGood(size_t size) // Compliant - custom malloc implementation that
// will guarantee deterministic execution time
{
// Custom implementation that provides deterministic worst-case execution
// time
}
void FreeGood(void* ptr) // Compliant - custom malloc implementation that will
// guarantee deterministic execution time
{
// Custom implementation that provides deterministic worst-case execution
// time
}
See also
none Rule A18-5-6 (required, verification / toolchain, non-automated)An analysis shall be performed to analyze the failure modes of dynamic memory management. In particular, the following failure modes shall be analyzed: (a) non-deterministic behavior resulting with nonexistence of worst-case execution time, (b) memory fragmentation, (c) running out of memory, (d) mismatched allocations and deallocations, (e) dependence on non-deterministic calls to kernel.
Rationale
The worst-case execution time and behavior of memory management functions are specific to each implementation. In order to use dynamic memory in the project, an analysis needs to be done to determine possible errors and worst-case execution time of allocation and deallocation functions. Note that standard C++ implementation violates some of this requirements. However, listed problems can be addressed by implementing or using a custom memory allocator.
## See also
none