Как мне создать модуль в MISRAC:2012, который следует Dir 4.12 и 4.8?
Этот вопрос относится к кодированию в ISO C99 в соответствии с рекомендациями MISRAC:2012.
Я ищу руководство по Dir 4.8 "Если указатель на структуру или объединение никогда не разыменовывается внутри единицы перевода, то реализация объекта должна быть скрыта" в сочетании с Dir 4.12 "Динамическое распределение памяти не должно использоваться".
При реализации Абстрактного Типа данных в C обычно ссылаются на ADT, используя дескриптор, который является указателем на структуру, описывающую внутреннее состояние ADT. Это может быть сделано с использованием непрозрачного указателя в соответствии с Директивой 4.8 с тем преимуществом, что внутренние детали остаются скрытыми от пользователя.
Обычно может существовать более одного из этих ADT, поэтому должен быть способ создать несколько дескрипторов. Это может быть решено путем выделения памяти для внутренних деталей, на которые ссылается дескриптор в функции инициализации, однако это не разрешено в Dir 4.12.
Другой вариант заключается в том, что подпрограмма инициализации получает указатель на статически распределенный дескриптор, предоставленный пользователем, однако это не может быть выполнено с использованием непрозрачных указателей.
Я иллюстрирую проблему ниже.
Module.h
struct module;
typedef struct module module_t; /* Module handle is only available to the world as an incomplete type. This allows us to satisfy MISRAC 2012 Dir 4.8.*/
Module.c
#include "module.h"
struct module
{
uint8_t value;
};
module_t* module_get_a_handle(void)
{
return (module_t*)malloc(sizeof(struct module)); /* MISRAC 2012 Dir 4.12 disallows dynamic memory allocation.*/
}
User.c
#include "module.h"
module_t* module_handle;
module_handle = module_get_a_handle();
Проблема также описана в этом вопросе Статическое распределение непрозрачных типов данных, однако это не обсуждается в отношении рекомендаций MISRAC:2012.
Одно из описанных решений заключается в использовании статически распределенного пула дескрипторов, которые становятся доступными для клиентского кода. Это решение кажется технически совместимым; однако, похоже, что концепция динамического распределения памяти все еще существует здесь. Я бы сказал, что, хотя дескрипторы статически размещены, компилятор не может определить во время компиляции, будет ли достаточно доступных дескрипторов для программного обеспечения для правильной работы.
Моим решением этой проблемы было бы написать отклонение от Dir 4.8 и использовать непрозрачные указатели и строгое соглашение об именах, которое дает пользователям понять, что внутренние детали ADT не должны изменяться.
Мне любопытно, есть ли хорошо принятый метод для решения этой проблемы, который соответствует Dir 4.8 и Dir 4.12 и не нарушает никаких других правил MISRAC:2012. Любые комментарии будут с благодарностью.
1 ответ
Кажется, вы поняли и проблему, и решение: используйте статический пул памяти внутри каждого ADT.
Однако этот пул должен быть ограничен определенным максимальным пределом, который должен быть жестко закодирован. По сути, вы будете реализовывать пул как static
буферизуйте в области видимости файла и отслеживайте "выделенный" размер с помощью переменной счетчика. Для каждого добавляемого элемента вы проверяете счетчик по максимальному пределу.
В случае, если вам не хватит места, ваша программа узнает об этом и сможет безопасно обработать эту ошибку. Не должно быть причины, по которой вам не хватает места. Это будет означать, что у вас есть ошибка дизайна. Вы наверняка должны быть уверены, что во время компиляции у вас не останется свободного места. Или, если нет, по крайней мере во время тестов покрытия кода.
Директива 4.12 касается динамического выделения памяти в куче с malloc/free
, Использование этих функций и кучи, является де-факто C стандартным определением термина динамическое выделение памяти. Это ничего не значит.
Существует несколько проблем с динамическим распределением: недетерминированное время выделения, сегментация, утечки памяти и т. Д. И т. Д.
Сама по себе "динамичность" не является проблемой, поскольку поведение программы остается детерминированным. Стандарты безопасности всегда касаются динамического выделения памяти в куче, поскольку это подразумевает недетерминированное поведение, что является основным грехом в разработке программного обеспечения, критически важного для безопасности.
Для многих распространенных встраиваемых систем, таких как приложения для микроконтроллеров с открытым железом /RTOS, динамическое распределение просто не имеет никакого смысла.
Таким образом, пул статической памяти не является "динамическим распределением памяти". В противном случае использование стека также будет считаться "динамической памятью", и вообще невозможно будет написать какое-либо полезное программное обеспечение.