静态程序分析:cppcheck 标记变量声明时的冗余赋值

Posted

技术标签:

【中文标题】静态程序分析:cppcheck 标记变量声明时的冗余赋值【英文标题】:Static program analysis: cppcheck flags redundant assignment on declaration of variable 【发布时间】:2019-06-29 19:35:12 【问题描述】:

想象一下:

#define OK 0
#define ERROR -1

int foo(void) 
int rv = OK;

rv = bar();

return rv;

在这种情况下,cppcheck 会将行 int rv = OK; 标记为带有 Message: Variable 'rv' is reassigned a value before the old one has been used. 的冗余分配

我想知道为什么会这样,我认为初始化变量是正确的做法,不是吗?

【问题讨论】:

如果 rv 在后者之前未使用,则警告是合法的。在两者之间放置一个printf("%d\n", rv);,看看该工具现在是否考虑代码声音(它最好)。您完全按照所示编写的代码会更好,就像 int rv = bar(); 一样,这就是警告试图告诉您的全部内容。 在某些情况下,初始化可能是有害的,因为它会隐藏一些不相关的未初始化变量的使用,但设置为 init 值。我个人不喜欢使用虚拟值进行初始化(正如许多编码规则所要求的那样),因为它们会阻止您利用现代工具。此外,在您的情况下,我至少希望它设置为 ERROR,因为绝对没有理由让代码在什么都不做时返回成功。但这只是我的意见...... 您可以将函数缩减为int foo(void) return bar(); ,完全避免rv。 (你甚至可以考虑使用static inline int foo(void) return bar(); 。)如果做不到这一点,你可以使用int foo(void) int rv = bar(); return rv; 。如果您使用调试器单步执行代码,这将具有一些优势。 【参考方案1】:

就像在 cmets 中已经提到的那样 - 您分配一个值并立即覆盖它而不使用初始值。

您提供的示例对于将所有变量声明放在顶部的代码很常见,在这种情况下,即使从未使用过,最好提前初始化它们。

该示例还可能指的是过去存在中间代码的情况,此后该代码已被删除,因此您可以按照 cmets 中的建议将其合并为一行。

在那些情况下,它只是关于干净的代码,因为它是不必要的。

但是想象一下这种情况:

extern int bar();

int foo(void) 
    int rv = bar();
    rv = bar();

    return rv;

这表明您可能忘记了中间返回值的处理。在这段代码中,这似乎很明显,但想象一下,有几个调用会覆盖它,或者中间有更多的逻辑,你可能会忽略它。

clang-tidy/Clang 静态分析器还通过clang-analyzer-deadcode.DeadStores 检查:Value stored to 'rv' during its initialization is never read 警告第二种情况。

【讨论】:

以上是关于静态程序分析:cppcheck 标记变量声明时的冗余赋值的主要内容,如果未能解决你的问题,请参考以下文章

静态代码分析工具(如 CppCheck)与将编译器警告设置为更严格的级别 [关闭]

静态分析工具Cppcheck在Windows上的使用

寻找用于 Java 开发的类似 Cppcheck 的工具 [关闭]

静态代码检查工具 cppcheck 的使用(可分别集成到VS和QT Creator里)

使用 compile_commands.json 时的 Cppcheck 内联抑制

自定义 cppcheck 规则集