【问题标题】:Misra C Rule 12.2 - false positive warning?Misra C 规则 12.2 - 误报警告?
【发布时间】:2015-09-13 21:40:15
【问题描述】:

我的 CCS 6.1 ARM 编译器(用于 LM3Sxxxx Stellaris)抛出警告:

“MISRA 规则 12.2。表达式的值在标准允许的任何评估顺序下都应相同”

以下代码:

typedef struct {
  ...
  uint32_t bufferCnt;
  uint8_t buffer[100];
  ...
} DIAG_INTERFACE_T;

static DIAG_INTERFACE_T diagInterfaces[1];

...
DIAG_INTERFACE_T * diag = &diagInterfaces[0];
uint8_t data = 0;
diag->bufferCnt = 0;
diag->buffer[diag->bufferCnt++] = data; // line where warning is issued
...

我的代码中没有发现问题。是误报还是我的错误?

【问题讨论】:

  • 我认为使用增量\减量运算符的返回值是一个非常糟糕的主意,无论标准对序列点等有何规定。最好将其拆分为单独的行以避免任何歧义并使其对任何人(包括您自己或编译器)都更具可读性。
  • 分析器很少聪明到可以完全消除可能的混叠。只需将该增量运算符保留在单独的语句中,它就会停止抱怨。
  • 好吧,如果我使用:diag->buffer[diag->bufferCnt] = data; diag->bufferCnt++;,第一个语句中的警告仍然存在。但是我在下面看到了答案,请在此处查看我的评论。
  • 您的分析仪似乎真的很糟糕。提交错误报告。在这种情况下,我认为他们只是列出了错误的错误号。该行违反了 MISRA,但不违反规则 12.2。

标签: c misra


【解决方案1】:

diag->bufferCnt++ 放在单独的语句中(正如 OP cmets 中的 Hans 所建议的那样)并且不应出现警告。

但是关于 MISRA 规则 12.2,我发现您的程序中没有违反 12.2(您的语句中有一个序列点并且没有未指定的行为),我认为这是您的 MISRA 软件中的一个错误。

有关信息,MISRA 中还有一条建议性 12.13 规则说:

(MISRA-C:2004, 12.13) “增量 (++) 和减量 (--) 运算符不应与表达式中的其他运算符混合”

MISRA 的问题是它们的术语使用远非完美,因为 12.3,而 ->= 是 C 运算符,在解释中他们似乎只谈论算术运算符...

【讨论】:

  • 请参阅我上面的评论,将单独的声明放在此处没有帮助。但见下文,这是 IMO 的正确答案。应使用专用的独立于编译器的 MISRA 检查器。
  • @tk_ 应该注意的是,12.13 是一个非常好的规则,所以 ++ 应该在它自己的一行上,即使它不喜欢抱怨工具。
  • @Lundin 我不这么认为。我个人更喜欢这个解决方案。如果有许多连续语句填满缓冲区(使用各种值),则方法diag->buffer[diag->bufferCnt++] = 更具可读性并且代码更紧凑。如果只有一个这样的陈述,那么我承认,分成两个陈述并没有什么坏处。
  • @tk_ 这样的代码通常是有问题的,并且也违反了 MISRA。更好的代码:diag->buffer[0] = data1; diag->buffer[1] = data2; 等等。最后你写diag->bufferCnt = absolute_value;。这使您可以编写自记录的确定性代码。读者不想知道每个数据项放置的确切索引吗?如果您担心代码在维护期间被修改,您可以添加各种静态断言。
  • @Lundin 这个 12.3 规则还禁止在 memcpystrcpy 实现中用于年龄的非常惯用的表达式,如 (*s1++ = *s2++)
【解决方案2】:

虽然您没有指明,但这是 MISRA-C:2004,规则 12.2,现在是 MISRA-C:2012 规则 13.2。正如 oauh 所说,这与“评估顺序”无关。

我强烈建议您参考 MISRA-C:2012,即使您需要符合 MISRA-C:2004,但 MISRA-C:2012 会有所帮助,因为它已经阐明了许多指南,包括其他基本原理、解释和例子。

您不应该只使用编译器来检查 MISRA-C 的兼容性,这很好,但编译器 #1 的目标不是警告您它专门利用的语言的所有陷阱和陷阱(优化)。它们也不是很精确,就像在这种情况下一样。此外,翻译单元中有许多未定义的行为,编译器无法警告。最好还使用专用的 MISRA 静态分析工具,该工具不是特定于编译器的,但从 ISO C 标准的角度来看,它会警告所有不可预测的构造,而不是特定的实现。

正如 oauh 所说,这违反了 MISRA-C:Rule 12.13,现在是 MISRA-C:2012 Rule 13.3,已放宽允许 ++ 和 -- 与其他运算符混合,前提是++ 或 -- 是副作用的唯一来源(在您的情况下,赋值也是 C 术语中的副作用)。

规则并不重要,即它定义明确的行为,但前缀版本和后缀版本产生的不同值可能会导致混淆,因此它是“建议性的”,意味着不需要正式的偏差(同样,一个体面的 MISRA -C 工具可以让您抑制这种特定的违规行为)。

【讨论】:

  • 谢谢,我认为这是正确的答案。我什至不知道有 MISRA 2012。我们试图检查 IAR 中的 MISRA 98 和 CCS 中的 MISRA2004 - 它是库代码。好吧,但是我理解这一点,我们将按照您的建议使用专用工具(无论如何,我的目标是找到一些独立于编译器的解决方案)。我只是希望 MISRA 2012 在从 MISRA 98 迁移到 MISRA 2004 时不会带来另一个“惊喜”(例如几乎每条语句中的警告)。
  • @tk_ 您可以在 misra-c.com 以大约 40 美元的价格获得 MISRA-C:2012 pdf - 它本身就是一个非常好的参考,仅用于 c 编程(比 MISRA-c 好得多: 2004 年文件)。不幸的是,大多数声称支持 MISRA-C 的工具都勉强够用——甚至是一些昂贵的工具。
  • 感谢您提供价格信息。我们肯定需要它和一个好的独立检查器。
猜你喜欢
  • 2015-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多