【问题标题】:MISRA-C error in struct array initialization结构数组初始化中的 MISRA-C 错误
【发布时间】:2015-10-21 23:54:14
【问题描述】:

我有以下几点:

typedef struct
{
   uint8_t BlockID;
   uint32_t Copies;
   uint16_t Size;
}NVMM_ConfigType;

const NVMM_ConfigType NvmmCnf_Layout[6] =
{
   {  1, 1,   4},
   {  2, 3,   4},
   {  5, 5,  16},
   { 10, 1,   4},
   { 11, 2,  32},
   { 13, 1, 100},
};

这对我来说似乎很好,但是 MISRA-C 给出了以下错误:

MISRA C:2012 规则 10.3 违规:[R] 表达式的值不应分配给具有较窄基本类型或不同基本类型类别的对象

我试图弄清楚为什么会发生这种情况,但我只能看到它。在类似情况下,构建结果也受到此错误的困扰,我不知道为什么。

有人知道发生了什么吗?

编辑:我还尝试显式转换每个值,但仍然得到相同的错误:

const NVMM_ConfigType NvmmCnf_Layout[6] =
{
    {  (uint8_t)1, (uint32_t)1,   (uint16_t)4},
    {  (uint8_t)2, (uint32_t)3,   (uint16_t)4},
    {  (uint8_t)5, (uint32_t)5,  (uint16_t)16},
    { (uint8_t)10, (uint32_t)1,   (uint16_t)4},
    { (uint8_t)11, (uint32_t)2,  (uint16_t)32},
    { (uint8_t)13, (uint32_t)1, (uint16_t)100},
};

【问题讨论】:

  • 我在这里没有看到任何问题......当然不是 R10.3。错误是针对哪一行?
  • 请使用下面评论中引用的类型转换显示您的代码版本,“我也尝试转换每个值,但仍然遇到相同的错误。”
  • @Andrew:错误出现在左大括号处,即“=”之后的那个
  • @m4l490n 我注意到您的最新编辑,当您知道它没有意义并且使代码过于冗长实际上不合规时,花时间使工具静音;-)

标签: c misra array-initialization


【解决方案1】:

当我使用 PC-Lint 检查 Misra 规则时,我经常发现自己需要在常量中添加 u 后缀:

const NVMM_ConfigType NvmmCnf_Layout[6] =
{
   {  1u, 1u,   4u},
   {  2u, 3u,   4u},
   {  5u, 5u,  16u},
   { 10u, 1u,   4u},
   { 11u, 2u,  32u},
   { 13u, 1u, 100u},
};

这消除了intunsigned 的转换。

如果这还不够,那么强制转换:

const NVMM_ConfigType NvmmCnf_Layout[6] =
{
   { (uint8_t ) 1u, 1u, (uint16_t )  4u},
   { (uint8_t ) 2u, 3u, (uint16_t )  4u},
   { (uint8_t ) 5u, 5u, (uint16_t ) 16u},
   { (uint8_t )10u, 1u, (uint16_t )  4u},
   { (uint8_t )11u, 2u, (uint16_t ) 32u},
   { (uint8_t )13u, 1u, (uint16_t )100u},
};

【讨论】:

  • 我也尝试了这两个选项,但仍然失败。一切都导致该工具无法正常工作的结论。
  • @Doug 这是 MISRA-C:2012,而不是 MISRA-C:2004。
  • @Veriloud,您的说法是正确的,但我不明白它与我的回答有何关系。您是说使用 PC-Lint 来满足 MISRA-C:2012 合规性没有这个问题吗?
  • @Doug,是的,这是对 MISRA 2004 的违反,但这是多余的,而且 MISRA-C 2012 同意,为什么不呢?我是 MISRA-C:2012 的忠实粉丝,这是众多原因之一。
  • 如果 PC-Lint 将此标记为 MISRA-C:2012 问题,这是错误的,但不足为奇,它不是同类产品中最好的。
【解决方案2】:

(嗨,这是一个新帐户,所以我还不能使用 cmets 部分要求进一步澄清,所以请原谅冗长的回复)

具体而言,本规则 10.3 与 MISRA-C:2012(最新标准)有关,它比以前的版本有了很大的改进,因为在解释 MISRA 的基本原理方面付出了更多努力,以及更多的合规和非合规的例子。

该规则的基本原理是:由于 C 允许自动执行不同算术类型之间的赋值,因此使用这些隐式转换可能会导致意外结果,并可能丢失值、符号或精度。 MISRA_C:2012 有一个基本类型模型来帮助在可能发生这种情况时发出警告。

规则说明还包括规则的例外情况。对于规则 10.3,一个例外是:一个本质上是有符号类型的非负整数常量表达式可以分配给本质上是无符号类型的对象,如果它的值可以用那个类型来表示。

不清楚您的工具报告违规行为的确切行和列(它应该)。更好的工具还将提供有关违反规则的确切部分的更详细信息(例如,如果您在第一次分配给 8 位时有 128 而不是 1,则该工具应该非常明确地说明这一点)。

无论如何,我(我的工具也没有)在这里看到任何违反 10.3 的行为。

由于这是一个“可判定”的规则,如果这是对安全至关重要的代码,我会担心这个工具,除了它会浪费你的时间。

大多数工具都允许您隐藏警告并记录原因(在这种情况下,这是工具中的错误)。

如果您的工具供应商需要更多信息,您可以在http://www.misra-c.com 的讨论论坛中发布您的问题,以获得官方答案并将其转发给供应商。

【讨论】:

  • 谢谢,我会通知供应商,因为我认为该工具与 MISRA-C 存在问题。顺便说一句,该工具是 Altium 的 TriCore Eclipse IDE v5.0r2
  • 正如我所说,MISRA-C:2012 是一个很大的改进,因此它成为其他安全关键行业(汽车除外)的基本 C 编码标准。但是,MISRA 组织没有针对这些工具的认证或合规计划,由用户决定哪些工具最能满足他们的需求,并最好地帮助他们填写合规矩阵。
【解决方案3】:

嗯,该规则实际上将无法设置 8 位寄存器,因为算术运算以 int 或更大 (usual arithmetic conversions) 的形式执行。拒绝 MISRA 作为编码标准的另一个理由。

我假设您必须将初始化程序中的每个值都转换为相应字段的类型。但正如引用的规则,那仍然是违规行为。

【讨论】:

  • 我也尝试过强制转换每个值,但仍然出现相同的错误
  • 您能解释一下为什么您认为“该规则将使设置 8 位寄存器实际上不可能”吗?
  • 没有人应该信奉宗教,但应该学习和理解指南背后的原因......
  • @Olaf - 确实......这就是我们编写本书前六章的原因。但是太多人阅读了规则而忽略了其余部分!
  • 也许我们应该将其移至 Chat... 我很想知道您为什么会有这种感觉 :-)
猜你喜欢
  • 1970-01-01
  • 2011-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-23
  • 2010-12-06
相关资源
最近更新 更多