Смена гибкого массива на указатель - PullRequest
1 голос
/ 11 мая 2019

Я работаю, чтобы избавиться от нарушений MISRA в моем коде C.Это нарушает правило 18.7 .

struct abc {
  struct header;
  uint8_t data[]; /* Line 1 */
};

Здесь строка 1 вызывает нарушения MISRA.

Я пытался преобразовать его в:

struct abc {
  struct header;
  uint8_t *data;
};

Можем ли мы поступить так, как описано выше, или это что-то нарушает?

Ответы [ 3 ]

2 голосов
/ 11 мая 2019

Ваше решение семантически отличается и не будет работать, даже если оно устранит нарушение.

Целью здесь является создание структуры, которая может выступать в качестве заголовка для непрерывных данных, следующих за ним. Так, например, если у вас есть:

struct Message
{
    struct abc info ;
    char data[128] ;
}  message ;

Так, что message.info.data и message.data относятся к одной и той же вещи, а приведение struct abc к struct Message позволяет определить функцию для передачи любого объекта с заголовком struct abc. Эффективно поддерживающий полиморфизм в С.

Замена на:

struct abc 
{
  struct header;
  uint8_t* data;
};

семантически отличается, поскольку член data не ссылается на данные, смежные с header. Семантика копирования также различается, и вряд ли в контексте кода, использующего исходную структуру, он будет работать так, как задумано.

GCC поддерживает следующий синтаксис:

struct abc 
{
  struct header;
  uint8_t data[0] ;
} ;

но, скорее всего, это не соответствует требованиям MISRA. Соответствующее решение должно иметь:

struct abc 
{
  struct header;
  uint8_t data[1] ;
} ;

Но при этом вставляется дополнительный символ, и любой код, который использует его в качестве заголовка, может потребоваться учитывать это при доступе к данным через член data.

1 голос
/ 13 мая 2019

Все системы, связанные с безопасностью, запрещают динамическое выделение памяти, и поэтому MISRA-C: 2012 делает то же самое.Это обоснование для правила 18.7: гибкие члены массива тесно связаны с динамическим размещением и поэтому не допускаются.

Причина, по которой динамическое размещение запрещено, заключается в том, что в такого рода не может быть недетерминированного поведения.системы.Кроме того, не имеет никакого смысла использовать динамическое распределение в приложениях микроконтроллеров / RTOS.

Вы можете поменять элемент гибкого массива на указатель, если это имеет смысл для вашего приложения.Но если это какой-то тип заголовка протокола или структуры данных, вы, вероятно, захотите использовать массив фиксированного размера.(И заполнение структуры разума: хранение протоколов передачи данных в структурах может быть проблематичным из-за выравнивания и порядка байтов.)

0 голосов
/ 11 мая 2019

Да, вы можете, так как это делает размер структуры детерминированным и статичным, но это также заставляет вас выделять, а затем освобождать необходимое пространство для data с malloc() и free() или явно указывать на некоторые уже доступное место где-то, каждый раз, когда вы создаете структуру.

То, что вы, вероятно, хотите здесь сделать, это указать определенную длину вашего массива. Однако если эта структура предназначена для фактического описания заголовка блока данных, вы можете использовать data[1], а затем позволить вашему индексу превышать это значение для доступа к остальным (хотя ISO C запрещает массивы 0 длины).

...