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

问题描述 投票:7回答:2

检查时

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

是的

  • 一个noop
  • 但是让编译器/分析器认为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发出“未初始化的警告”?

c fread garbage clang-static-analyzer false-positive
2个回答
1
投票

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

如果c[0]失败,分析器应该理解检查保证fread不被读取将需​​要分析器理解fread()函数的语义。对于任何非平凡的代码而言,这是一项计算成本高昂的任务,并且需要查看库源或标准库语义的编码 - 这是可能的,但只会发现涉及“已知函数”的一小部分问题。

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

char c[20] = {0} ;

0
投票

我会说编译器不应该知道函数fread()的工作原理。从编译器的角度来看,fread()可能会也可能不会修改'c'。

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

© www.soinside.com 2019 - 2024. All rights reserved.