2

我正在努力消除我的 C 代码中出现的 MISRA 违规。它违反了规则 18.7

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

在这里,第 1 行导致了 MISRA 违规。

我试图将其转换为:

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

我们可以像上面那样做还是违反了什么?

4

3 回答 3

4

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

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

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

这样message.info.datamessage.data引用相同的东西并将 a 转换struct abc为 astruct Message允许定义一个函数来传递任何带有struct abc标头的对象。有效地支持 C 中的多态性。

将其替换为:

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成员访问数据时可能需要适应它。

于 2019-05-11T10:49:02.993 回答
1

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

禁止动态分配的原因是在这类系统中不能存在非确定性行为。此外,在微控制器/RTOS 应用程序中使用动态分配没有任何意义。

如果它对您的应用程序有意义,您可以将灵活的数组成员交换为指针。但如果它是某种协议或数据结构标头,您可能需要一个固定大小的数组。(并且考虑结构填充:由于对齐和字节序,将数据通信协议存储在结构中可能会出现问题。)

于 2019-05-13T06:56:52.957 回答
0

是的,您可以,因为它使结构大小具有确定性和静态性,但它也迫使您分配然后释放所需的空间datawith malloc()and free(),或者在每次实例化结构时显式使其指向某处已经可用的空间。

您可能想要在这里做的是为您的数组指定一个确定的长度。但是,如果此结构旨在实际描述数据块的标头,则可以使用data[1]then 让索引超过此值来访问其余部分(尽管 ISO C 禁止 0 长度数组)。

于 2019-05-11T09:50:58.957 回答