我正在努力摆脱C代码中出现的MISRA违规行为。这违反了第18.7条。
struct abc {
struct header;
uint8_t data[]; /* Line 1 */
};
此处,第1行引起了MISRA违规。
我试图将其转换为:
struct abc {
struct header;
uint8_t *data;
};
我们可以喜欢上面的内容吗,还是违反了某些规定?
答案 0 :(得分:2)
您的解决方案在语义上有所不同,即使清除了违规情况也不会起作用。
此处的目的是创建一个结构,该结构可以用作紧随其后的连续数据的标头。例如,如果您有:
struct Message
{
struct abc info ;
char data[128] ;
} message ;
message.info.data
和message.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)
是的,您可以这样做,因为它使结构大小确定且静态,但是它也迫使您分配,然后用data
和malloc()
释放free()
所需的空间,或者显式地每次实例化结构时,使其指向某处一些已经可用的空间。
您可能要在此处指定数组的一定长度。但是,如果此结构实际上是用来描述数据块的标头,则可以使用data[1]
,然后让您的索引超过该值来访问其余数据(尽管ISO C禁止使用0长度的数组)。