【问题标题】:C/C++ default value/value assigned to variable is never used从未使用分配给变量的 C/C++ 默认值/值
【发布时间】:2018-05-16 13:41:15
【问题描述】:

我喜欢总是初始化局部变量,例如

int32_t result = 0;

我认为这是一种很好的编程风格,因为“结果”永远不会未初始化,无论是否遵循 if-constructs 设置它。

但现在我正在尝试一个静态代码检查器工具(用于 IAR 嵌入式工作台的 C_STAT),这抱怨在下面的函数中,MISRA-C++ 规则 2008-01-06(“不应包含非易失性变量的实例被赋予以后从未使用过的值”)和 MISRA C:2012 规则 2.2c(“无死代码”)和 CWE 563(“未使用的变量”)被违反。

// gets signal1 - signal2 (checks range of value)
int16_t getSignalDifferenceFromFloat(float signal1, int16_t signal2)
{
    int32_t result = 0; // <-- this assignment makes the violation 
                        // ... but I feel better with it

    if (signal1 > 65535.0)
    {
        // because result cannot be smaller than the max value of TSignal
        result = 32767;
    }
    else if (signal1 < -65535.0)  // <-- here an else  was missing
    {
        // because result cannot be larger than the min value of TSignal
        result = -32768;
    }
    else
    {
        result = (int32_t)signal1 - (int32_t)signal2;

        if (result < -32768)
        {
            result = -32768;
        }
        else if (result > 32767)
        {
            result = 32767;
        }
    }

    return (int16_t) result;
}

原始问题:您对此有何看法?

新问题:

  1. 是否存在要求始终立即初始化已声明的局部变量的良好编码标准?
  2. 代码检查器是否过于迂腐(一些编译器不会在这个地方抱怨,但会抱怨变量将完全未被使用)?我做了很多年,但我不记得我在哪里看到的。

更新:在此期间(2021 年 9 月),我将 pclint 与默认设置一起使用。它还检查 misra C++ 规则 0-1-6(随后未使用的变量)和其他规则,但不会抱怨此示例。如果我更改代码并且不返回此变量,则会按预期出现警告。我认为pclint在这里没有给出警告是正确的。

【问题讨论】:

  • 你确定吗?你的第一个 if 毫无意义……第二个 if/else 总是会改变 result 的值。
  • 第一次分析似乎不太相关。即使是最基本的优化编译器也可以消除不必要的初始化。
  • 首先,请注意,C 和 C++ 是两种非常不同的语言,虽然部分看起来相似,但可能有细微的细节会在行为和语义。其次,将int32_t 用于要转换为int16_t 的变量有什么用?最后,您确定您的if 后跟if ... else 吗?你不应该有if ... else if ... else吗?
  • 这些是您遇到的唯一静态分析问题吗?整数与双精度数或幻数的不必要比较怎么办?
  • 你需要问一个不同于“你对此有何看法?”的问题,例如“我怎样才能编写代码使其符合本地标准和 MISRA 标准?”。在 SO 上征求意见是 OT。

标签: c++ c initialization default misra


【解决方案1】:

我同意 MISRA。

对变量进行不必要的初始化可能会导致代码草率,因为它会破坏检查未初始化变量的工具。

在您的特定情况下,您可以将 result 本地化为最终的 else 情况,并在其他情况下过早返回。但这也不符合每个人的口味。

【讨论】:

  • 问题类型请教;但这没有理由给出一个 - 意见是对 SO 的 OT。
  • @Clifford:我认为这是“客套话”,即必须坚持这种风格。
  • @Bathsheba:我们的内部编码风格禁止过早返回。 Misra C++ (2008-6-6-5) 也是如此。
  • @Bathsheba:这就是为什么这只是你的意见:我(几乎)会坚持相反的意见。现在你明白为什么我们不回答关于 SO 的主观问题了吗?你提出的东西是事实,事实上,不是事实。
  • 如果您有足够的权威来源支持它,它不再是一种观点。 MISRA-C 禁止死代码,它被定义为可以在不影响程序结果的情况下删除的代码,但程序员明确转换为(void) 的表达式除外。死代码被视为安全隐患。权威来源:MISRA-C:2012、IEC61507、ISO26262、DO-178C。
【解决方案2】:

静态分析器会应用您定义的规则 - 其中一些规则会发生冲突,因为您需要将它们设置为与您当地的编码标准相匹配。我想还有一条规则可能会或可能不会启用 要求 初始化所有变量;你不能两者都做。

选择符合您首选标准的非冲突规则集。您选择哪个是一个意见问题,所以不是一个真正有效的 SO 问题。

【讨论】:

    【解决方案3】:

    大多数优秀的静态分析器都会为您提供数据流分析 - 它会警告您可能的路径会留下未初始化的变量。

    以您为例,假设您(不小心)错过了后来的一项作业,SA 不会检测到这一点:

    /// gets signal1 - signal2 (checks range of value)
    int16_t getSignalDifferenceFromFloat(float signal1, int16_t signal2)
    {
        int32_t result = 0; // <-- this assignment makes the violation 
            // ... but I feel better with it
    
        if (signal1 > 65535.0)
        {
            // commented out this line
            // No data-flow anomoly detected
            // result = 32767;
        }
    
        // Snip rest of code
    
        return (int16_t) result;
    }
    

    无论如何,MISRA 指南都不是完美的,但我们会尽量避免显而易见的情况……而且未初始化的变量很容易检测到 - 只要您不试图捏造问题。

    这有点像贴一个演员表,只是为了关闭静态分析工具......

    [查看免责声明简介]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多