AUTOSAR C++14 Rule A18-5-5

Функции управления памятью должны гарантировать следующее: (a) детерминированное поведение, заканчивающееся с существованием времени выполнения худшего случая, (b) предотвращение фрагментации памяти, (c) постарайтесь не заканчиваться память, (d) предотвращение несовпадающих выделений или освобождения, (e) никакая зависимость от недетерминированных вызовов ядра

Описание

Управляйте определением

Функции управления памятью должны гарантировать следующее: (a) детерминированное поведение, заканчивающееся с существованием времени выполнения худшего случая, (b) предотвращение фрагментации памяти, (c) постарайтесь не заканчиваться память, (d) предотвращение несовпадающих выделений или освобождения, (e) никакая зависимость от недетерминированных вызовов ядра.

Объяснение

Когда вы реализуете пользовательские функции управления памятью, убедитесь, что ваша реализация исправляет эти ошибки управления общей памятью, которые могут влиять на устойчивость и правильность вашего приложения:

  • Недетерминированное время выполнения худшего случая (WCET) операций выделения и освобождения.

    Чтобы обеспечить детерминированный WCET, убедитесь, что функция может быть выполнена без контекстного переключения или системных вызовов. Предсказуемый WCET важен в определении соответствующей схемы планирования, которая соответствует ограничениям синхронизации в критических по отношению к безопасности встраиваемых системах.

  • Несовпадающие функции выделения и освобождения.

    Освобождение памяти с функцией, которая не совпадает с функцией выделения, может вызвать повреждение памяти или неопределенное поведение.

  • Недопустимый доступ к памяти.

    При попытке получить доступ к памяти, которая является логически или физически недопустима, результаты операции в неопределенном поведении или отказе сегментации.

  • Ошибки из памяти.

    Чтобы постараться не исчерпывать память, ваш исполняемый файл должен выделить всю память, необходимую программе при запуске.

  • Фрагментация памяти.

    Фрагментация происходит, когда память выделяется по блокам, состоящим из нескольких несмежных участков. Если освобожденные блоки не являются достаточно большими, чтобы вместить будущие запросы выделения, остающаяся свободная память не может быть применимой, и ваша система может отказать.

В дополнение к пользовательским реализациям для операторов new и delete, необходимо обеспечить пользовательские реализации для низкоуровневых функций выделения и освобождения (malloc/free). Даже если вы не используете эти низкоуровневые функции в своем исходном коде, они могут произойти в соединенных библиотеках в вашем проекте.

Пользовательская реализация std::new_handler должен выполнить одну из этих операций:

  • Сделайте больше память доступной для выделений и возвратитесь.

  • Отключите программу, не возвращаясь к вызываемому.

  • Выдайте исключение типа std::bad_alloc или выведенный из std::bad_alloc.

Реализация Polyspace

Polyspace® проверки на эти проблемы управления памятью, которые могут привести к недетерминированному поведению:

  • Использование библиотечной функции C (malloc/calloc/realloc/free) выделить или освободить память в инициализациях локальной переменной.

    Polyspace не отмечает использование этих функций при выделении или освобождении глобальных переменных.

  • Использование неразмещения new и delete операторы.

  • Использование функционального dlsym(). Эта функциональная сила вызывает низкоуровневые функции выделения или освобождения, такие как malloc или calloc.

Поиск и устранение проблем

Если вы ожидаете нарушение правила, но не видите его, относитесь, чтобы Диагностировать, Почему Кодирующие Стандартные Нарушения Не Появляются как ожидалось.

Примеры

развернуть все

#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);

}

В этом примере Polyspace отмечает эти операции управления динамической памятью:

  • Выделение и освобождение указателя p1 с операторами неразмещения new и delete.

  • Выделение и освобождение локального указателя p3 с низкоуровневыми функциями malloc и free. Polyspace не отмечает использование этих функций при выделении или освобождении глобальных переменных.

  • Использование функционального dlsym() потому что вызовы функции malloc.

Polyspace не отмечает инициализацию указателя p2 потому что это использует оператор размещения new который создает указатель в предварительно выделенном буфере.

Проверяйте информацию

Группа: вспомогательная библиотека Языка
Категория: Необходимый, Частично автоматизированный
Введенный в R2021b