Main Content

AUTOSAR C++14 Rule A18-5-5

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

Since R2021b

Description

Rule Definition

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

When you implement custom memory management functions, make sure that your implementation addresses these common memory management errors that can affect the stability and correctness of your application:

  • Non-deterministic worst-case execution time (WCET) of allocation and deallocation operations.

    To provide a deterministic WCET, make sure that the function can be executed without context switching or system calls. A predictable WCET is essential in determining an appropriate scheduling scheme that meets the timing constraints in safety-critical embedded systems.

  • Mismatched allocation and deallocation functions.

    Deallocating memory with a function that does not match the allocation function can cause memory corruption or undefined behavior.

  • Invalid memory access.

    If you try to access memory that is logically or physically invalid, the operation results in undefined behavior or a segmentation fault.

  • Out-of-memory errors.

    To avoid running out of memory, your executable should allocate all the memory needed by the program at startup.

  • Memory fragmentation.

    Fragmentation occurs when memory is allocated over non-contiguous blocks. If the unallocated blocks are not large enough to accommodate future allocation requests, the remaining free memory might not be usable and your system might crash.

In addition to custom implementations for operators new and delete, you should provide custom implementations for low-level allocation and deallocation functions (malloc/free). Even if you do not use these low-level functions in your source code, they can occur in linked libraries in your project.

A custom implementation of std::new_handler must perform one of these operations:

  • Make more memory available for allocations and return.

  • Terminate the program without returning to the callee.

  • Throw an exception of type std::bad_alloc or derived from std::bad_alloc.

Polyspace Implementation

Polyspace® checks for these memory management issues that might result in non-deterministic behavior:

  • Use of C library function (malloc/calloc/realloc/free) to allocate or deallocate memory in local variable initializations.

    Polyspace does not flag the use of these functions when allocating or deallocating global variables.

  • Use of non-placement new and delete operators.

  • Use of function dlsym(). This function might call low-level allocation or deallocation functions such as malloc or calloc.

Troubleshooting

If you expect a rule violation but Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

#define _GNU_SOURCE
#include <malloc.h>
#include <dlfcn.h>
#include <iostream>

class Point
{
public:
    Point(int x1 = 0, int y1 = 0): x(x1), y(y1)
    {
    }
    ~Point();
private:
    int x, y;
};


void func1()
{
    unsigned char buffer[sizeof(int) * 2];
    Point* p1 = new Point(0, 0); // Non-compliant
    Point* p2 = new (buffer) Point(1, 1); // Compliant

    int* p3 = (int*)malloc(sizeof(int)); // Non-compliant

    //Use pointers

    delete p1; // Non-compliant
    p2->~Point();
    free(p3); // Non-compliant
}

void* customAlloc(size_t size)
{
    void* (*myAlloc)(size_t) = 
			(void* (*)(size_t))dlsym(RTLD_NEXT, "malloc"); // Non-compliant
					
	return myAlloc(size);

}

In this example, Polyspace flags these dynamic memory management operations:

  • The allocation and deallocation of pointer p1 with non-placement operators new and delete.

  • The allocation and deallocation of local pointer p3 with low-level functions malloc and free. Polyspace does not flag the use of these functions when allocating or deallocating global variables.

  • The use of function dlsym() because the function calls malloc.

Polyspace does not flag the initialization of pointer p2 because it uses a placement operator new which creates the pointer in a pre-allocated buffer.

Check Information

Group: Language support library
Category: Required, Partially automated

Version History

Introduced in R2021b