代码之家  ›  专栏  ›  技术社区  ›  ensc

叮当分析:如何避免“垃圾值”警示?

  •  0
  • ensc  · 技术社区  · 6 年前

    检查时

    #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;
    }
    

    有了叮当声,我明白了

    $ 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)
    

    真的有可能 c 此时是否包含垃圾?如果没有,我如何避免警告(没有明显的初始化 C )?

    更新

    因为这似乎是大家的共识,认为这是一种误报,我想重点谈谈如何避免这种警示。

    的确 fread() 是一个标准函数,分析程序应该知道它们的语义,例如 memset() 已经。但我对一种更通用的方法感兴趣,例如在库函数上。

    我会调用一些特殊函数(让我们调用它 assert_defined() )在某种程度上

        l = fread(c, sizeof c, 1, stdin);
        assert_defined(c, l * sizeof c);
    

    哪个是

    • 诺普
    • 但是让编译器/分析器认为 l * sizeof c 字节在 C 已初始化

    Clang知道像这样的注释吗

    inline static void assert_defined(void const *p, size_t cnt) 
       __attribute__((__dear_compiler_this_memory_is_not_garbage__(1,2)))
    {
    }
    

    或者有类似的把戏

    int i = i;
    

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

    0 回复  |  直到 6 年前
        1
  •  1
  •   Clifford    6 年前

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

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

    初始化阵列将避免此特定问题:

    char c[20] = {0} ;
    
        2
  •  0
  •   machine_1    6 年前

    我认为编译器不应该知道函数fread()的工作原理。从编译器的角度来看,fread()可以修改“c”,也可以不修改“c”。

    因此,如果在特定情况下没有显式初始化变量,编译器就只能发出警告。