clang-analyze:如何避免出现“垃圾价值”警告?

ens*_*nsc 7 c false-positive fread clang-static-analyzer garbage

检查时

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    char    c[20];
    size_t  l;

    l = fread(c, sizeof c, 1, stdin);
    if (l != 1)
        return 1;

    return c[0] == 42;
}
Run Code Online (Sandbox Code Playgroud)

用c,我得到

$ clang  --analyze -Xclang -analyzer-checker=alpha x.c
x.c:13:14: warning: The left operand of '==' is a garbage value
        return c[0] == 42;
               ~~~~ ^

$ clang -v
clang version 7.0.1 (Fedora 7.0.1-4.fc29)
Run Code Online (Sandbox Code Playgroud)

此时真的有机会c包含垃圾吗?如果没有,如何避免发出警告(没有对进行明显的初始化c)?

更新资料

因为这似乎是一个普遍的共识,那就是错误的肯定,所以我想集中讨论如何避免警告。

的确,这fread()是一个标准功能,分析人员应该在执行操作时就memset()已经知道了它们的语义。但是我对更通用的方法感兴趣,例如可以在库函数上使用。

我会assert_defined()以类似的方式调用一些特殊功能(让它调用它)

    l = fread(c, sizeof c, 1, stdin);
    assert_defined(c, l * sizeof c);
Run Code Online (Sandbox Code Playgroud)

这是

  • op
  • 但是让编译器/分析器认为l * sizeof cat c的字节已初始化

lang知道像这样的注释吗

inline static void assert_defined(void const *p, size_t cnt) 
   __attribute__((__dear_compiler_this_memory_is_not_garbage__(1,2)))
{
}
Run Code Online (Sandbox Code Playgroud)

还是有类似的技巧

int i = i;
Run Code Online (Sandbox Code Playgroud)

这可以防止gcc发出“未初始化的警告”?

Cli*_*ord 2

是的,如果失败的话,它可能包含垃圾fread()

为了使分析器了解c[0]如果失败则不会读取检查保证fread,需要分析器理解函数的语义fread()。对于任何重要的代码来说,这都是计算成本高昂的任务,并且需要查看库源代码,或者对标准库语义进行编码——这是可能的,但只能发现涉及“已知函数”的一小部分问题。

初始化数组将避免这个特定问题:

char c[20] = {0} ;
Run Code Online (Sandbox Code Playgroud)

  • 代码涵盖了“fread”失败的情况。问题是为什么分析器无法捕获它。 (2认同)
  • @Clifford 转储变量初始化是一种不好的做法,它隐藏了许多编译器会检测到的编程错误。 (2认同)