加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – g编译器中的“未初始化使用”警告

发布时间:2020-12-16 04:52:15 所属栏目:百科 来源:网络整理
导读:我正在使用g警告级别-Wall -Wextra并将警告视为错误(-Werror). 现在我有时会收到错误“变量可能在此函数中未初始化”. “有时”我的意思是我有两个独立的编译单元,它们都包含相同的头文件.一个编译单元编译没有错误,另一个编译单元给出上述错误. 头文件中的
我正在使用g警告级别-Wall -Wextra并将警告视为错误(-Werror).

现在我有时会收到错误“变量可能在此函数中未初始化”.

“有时”我的意思是我有两个独立的编译单元,它们都包含相同的头文件.一个编译单元编译没有错误,另一个编译单元给出上述错误.

头文件中的相关代码如下.由于功能很长,我只复制了下面的相关位.

确切的错误是:

‘cmpres’ may be used uninitialized in this function

我在下面用*标记了错误.

for (; ;) {
    int cmpres; // *
    while (b <= c and (cmpres = cmp(b,pivot)) <= 0) {
        if (cmpres == 0)
            ::std::iter_swap(a++,b);
        ++b;
    }
    while (c >= b and (cmpres = cmp(c,pivot)) >= 0) {
        if (cmpres == 0)
            ::std::iter_swap(d--,c);
        --c;
    }
    if (b > c) break;
    ::std::iter_swap(b++,c--);
}

(cmp是一个带有两个指针x和y的仿函数,如果* x< * y,* x == * y或* x> * y,则返回-1,0或1.其他变量是指向相同的数组.)

这段代码是更大函数的一部分,但变量cmpres在其他地方使用.因此,我无法理解为什么会产生此警告.此外,编译器显然明白cmpres永远不会被未初始化读取(或者至少,它并不总是警告,见上文).

现在我有两个问题:

>为什么行为不一致?这个警告是由启发式生成的吗? (这是合理的,因为发出此警告需要控制流分析,这在一般情况下是NP难的,并且不能总是执行.)
>为什么警告?我的代码不安全吗?我已经开始意识到这个特别的警告,因为它使我免于在其他情况下很难发现错误 – 所以这是一个有效的警告,至少有时候.它在这里有效吗?

解决方法

诊断没有假阴性或阳性的未初始化变量的算法必须(作为子程序)包括解决 Halting Problem的算法.这意味着没有这样的算法.计算机无法在100%的时间内完成此任务.

我不知道GCC的未初始化变量分析是如何工作的,但我知道它对早期优化传递对代码所做的事情非常敏感.所以我有点不会惊讶你有时会得到误报.它确实区分了可以确定无法确定的情况 –

int foo() { int a; return a; }

产生“警告:’a’在此功能中未初始化使用”(强调我的).

编辑:我发现一个案例,最近版本的GCC(4.3及更高版本)无法诊断未初始化的变量:

int foo(int x)
{
    int a;
    return x ? a : 0;
}

早期优化注意到如果x非零,则函数的行为是未定义的,因此它们假设x必须为零并用“return 0”替换函数的整个主体.这种情况发生在产生使用过的未初始化警告的传递之前,所以没有诊断.有关详细信息,请参阅GCC bug 18501.

我部分地提出这一点,以证明生产级编译器可以通过两种方式获得未初始化的变量诊断错误,部分原因是它是未定义行为可以在执行时间向后传播的一个很好的例子.关于测试x没有任何未定义,但由于依赖于x的代码控制具有未定义的行为,因此允许编译器假定永远不满足控件依赖性并丢弃测试.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读