【问题标题】:Can gcc accurately catch useless conditionals?gcc 能准确捕捉无用的条件吗?
【发布时间】:2010-10-25 11:15:34
【问题描述】:

请检查以下代码:

if (foo->bar == NULL);
   foo->bar = strdup("Unknown");

我花了三个小时的最后一部分与 Valgrind 一起寻找泄漏,当我发现虚假的 ';' 时感觉非常很傻。

我知道上面的代码是有效的 C,但是我希望 gcc 能够告诉我是否使用条件作为语句。

是否有我可以通过的标志,以帮助将来发现此类错误?在我看来,gcc 将能够知道条件是否无用。

IE

if (1 == 1);
  code_that_is_always_reached_since_conditional_is_a_statement();

所有的 lints 都没有对此提出异议。 Valgrind 很高兴能找到这类东西.. 但实际上代码中的泄漏比最初分配指针的位置要晚得多。

感谢任何帮助,即使是“不,它不会那样做。”

编辑:

哇,感谢您如此快速而出色的回复!总而言之,以下是您的选择:

  • -Wextra 能收集到 -Wall 没有的各种东西,包括 空/无用的语句。
  • -Wempty-body 拾取无用的语句,由 -Wextra(但可以破坏旧版本的 gcc,适用于 4.3.x)

有些人可能会觉得 -Wextra 很烦人。您可能会对不同符号类型之间进行比较,但您知道只有当它们相同时才会进行比较。

int ret;
unsigned int i;

ret = foo(bar); /* foo() is known to return a signed errno on failure */
if (ret < 0)
  return 1;

/* Enter GCC complaining that ret differs in signedness
 * (but you know it doesn't and get the urge to cast it) */
for (i = 0; i < ret; i ++)
   ...

再次感谢您的提示!

【问题讨论】:

    标签: c gcc memory-leaks


    【解决方案1】:
    /* foo.c */
    int main() {
       if (1) ; 
       return 0;
    }
    
    gcc -Wextra -c foo.c
    foo.c: In function ‘main’:
    foo.c:2: warning: empty body in an if-statement
    

    【讨论】:

    • 我喜欢 -Wall 并不意味着 -Wall。了解 -Wextra 值得失去 2 个代表。
    • 这是为了向后兼容。在这一点上,文档非常清楚(甚至重复本身)。 Wall 说它会激活,“所有上述 -W 选项结合在一起。”,“这会启用所有关于一些用户认为有问题的结构的警告,并且很容易避免”和“以下 -W... 选项不是由 -Wall 暗示。”等。此外,许多警告重申 Wall 是否激活它。
    • @Matthew - 文档也几乎不可能浏览,因为它太大了。也许他们应该少重复一点……
    • 谢谢!我还收集了六种不同符号类型之间的比较,其中一种是危险的。我也有一个“假”;而不是'return false;' , -Wall 没有捡起。
    • 它非常庞大,因为有很多选择。他们可以把它分成几个部分(每个部分有不同的手册页),但对于我们这些拥有体面的寻呼机实际上变成 /more/ 工作的人来说。例如,zsh 就是这样做的,我觉得这很烦人。
    【解决方案2】:

    深入挖掘gcc手册后:

    -Wempty-body
        Warn if an empty body occurs in an `if', `else' or `do while' statement. This warning is also enabled by
    -Wextra.
    

    正如其他一些海报所写,-Wextra 应该这样做

    示例代码:

    int main(){
    
            if (0);
                    printf("launch missiles");
            return 0;
    }
    
    
    $gcc -Wempty-body foo.c
    warn.c: In function ‘main’:
    warn.c:5: warning: suggest braces around empty body in an ‘if’ statement
    

    【讨论】:

    • +1,很高兴能够压制-Wextra 处理的其他内容,例如两个不同符号的事物之间的比较(当你很清楚两者的值都是无符号时),即,如果其中一个值已签名,则不会进行检查。
    • 唯一的问题是,这会破坏早期版本的 gcc(4.2.x 或更早版本)。
    【解决方案3】:

    试试 -Wextra

    【讨论】:

      【解决方案4】:

      作为编译器的替代方案,我发现在代码上运行自动缩进器有助于发现这些情况。

      以 vim 为例:

      gg=G
      

      【讨论】:

        【解决方案5】:

        除了上述之外,如果您发现自己在使用 valgrind 或类似的执行分析器寻找错误时感到沮丧,您或许应该考虑使用静态分析工具,例如 lint。就个人而言,我使用PC-LINT,它可以捕获各种类型的错误。

        【讨论】:

        • OP 说 lint 没有解决这个问题……你相信它可以吗?
        • 刚刚检查过,PC-Lint 捕捉到了它,尽管它缺少“else”。我使用总是能捕捉到它的 VC++,因此我从未真正亲身遇到过它。我要说的是,在动态分析(valgrind、boundschecker 等)处于空白状态的情况下,静态分析可能会显示结果。当然反过来也是一样的。我发现将我所有的代码都整理一下是值得的。
        • PC-Lint 与 MISRA-C 规则文件相结合肯定会解决这个问题,因为它会抱怨在 'if' 语句之后缺少大括号。
        • if 语句后没有大括号可以是有效的 C89/99 ,这就是我使用的。我使用的 lintian 叫做夹板,它可以很好地拾取编译器没有的东西。例如,我使用 -Wno-unused 标志,因为我知道我有一些尚未连接在一起的静态函数,但这也会抑制未使用变量的警告。因此,夹板可以解决这个问题,等等。 smaci 是正确的,因为必须有 lints 和编译器标志的良好组合,尤其是当您将编译器设置为将警告视为错误时。我还在酝酿那个神奇的食谱:)
        猜你喜欢
        • 1970-01-01
        • 2021-07-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-23
        • 1970-01-01
        相关资源
        最近更新 更多