将灵活数组更改为指针

时间:2019-05-11 09:30:09

标签: c misra flexible-array-member

我正在努力摆脱C代码中出现的MISRA违规行为。这违反了第18.7条

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

此处,第1行引起了MISRA违规。

我试图将其转换为:

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

我们可以喜欢上面的内容吗,还是违反了某些规定?

3 个答案:

答案 0 :(得分:2)

您的解决方案在语义上有所不同,即使清除了违规情况也不会起作用。

此处的目的是创建一个结构,该结构可以用作紧随其后的连续数据的标头。例如,如果您有:

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

message.info.datamessage.data指的是同一事物,并且将struct abc强制转换为struct Message可以定义一个函数来传递带有{{ 1}}标头。有效地支持C语言中的多态性。

替换为:

struct abc

在语义上有所不同,因为struct abc { struct header; uint8_t* data; }; 成员不引用与data相邻的数据。复制语义也有所不同,在使用原始结构的代码上下文中,复制不太可能按预期工作。

GCC支持以下语法:

header

,但也可能不符合MISRA。符合要求的解决方案是:

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

但这会插入一个额外的字符,并且通过struct abc { struct header; uint8_t data[1] ; } ; 成员访问数据时,任何使用该字符作为标题的代码都可能需要容纳该字符。

答案 1 :(得分:1)

所有与安全相关的系统都禁止动态内存分配,因此MISRA-C:2012也是如此。这是规则18.7的基本原理:灵活的数组成员与动态分配紧密相关,因此是不允许的。

之所以禁止动态分配,是因为在这类系统中不能存在非确定性行为。此外,doesn't make any sense可以在微控制器/ RTOS应用程序中使用动态分配。

如果对您的应用程序有意义,则可以将柔性数组成员交换为指针。但是,如果这是某种协议或数据结构头的方式,则可能需要固定大小的数组。 (而且要注意结构填充:由于对齐和字节顺序,将数据通信协议存储在结构中可能会出现问题。)

答案 2 :(得分:0)

是的,您可以这样做,因为它使结构大小确定且静态,但是它也迫使您分配,然后用datamalloc()释放free()所需的空间,或者显式地每次实例化结构时,使其指向某处一些已经可用的空间。

您可能要在此处指定数组的一定长度。但是,如果此结构实际上是用来描述数据块的标头,则可以使用data[1],然后让您的索引超过该值来访问其余数据(尽管ISO C禁止使用0长度的数组)。