gpt4 book ai didi

Clang -Wconditional-uninitialized on struct member array 赋值

转载 作者:太空宇宙 更新时间:2023-11-04 04:16:06 26 4
gpt4 key购买 nike

我遇到了一些涉及 Clang -Wconditional-uninitialized 的异常行为。考虑以下示例:

typedef struct { int x[1]; } test_t;
test_t foo(void);
test_t foo() {
test_t t;
for(int i = 0; i < 1; i++) t.x[i] = 0;
return t;
}
int main() { }

编译,例如

clang -o test -Weverything test.c

给出以下警告:

test.c:6:12: warning: variable 't' may be uninitialized when used here [-Wconditional-uninitialized]
return t;
^
test.c:4:5: note: variable 't' is declared here
test_t t;
^
1 warning generated.

然而,切换线路:

    for(int i = 0; i < 1; i++) t.x[i] = 0;

    t.x[0] = 0;

不产生任何警告。请注意,使用 -Wconditional-uninitialized 就足够了,不必传递 -Weverything。两种情况下的 -O3 优化程序集是相同的,在两种情况下都发出了一个 xorl %eax, %eax。这是我可以创建的显示此行为的最小示例。

我对 Clang 的一些 -Weverything 输出持保留态度,但这在我看来像是一个错误,我很困惑。是否有某种我正在调用的未定义行为导致了这种情况,或者这是误报?保持 -Wconditional-uninitialized 启用通常是好主意还是坏主意?我在 Linux 上的 Clang 3.8.1 和 macOS 上的 (Apple) 9.1.0 上看到了相同的行为。

最佳答案

正如@R.. 在上面的评论中所建议的那样,我将其报告为 LLVM bug 38856 .显然,根据他们的说法:

-Wconditional-uninitialized is expected to have false positives: it warns in cases where a simple control flow analysis cannot prove that a variable was written to prior to each use. It is not field-sensitive nor data flow sensitive, so it cannot tell the difference between writing to one array element and writing to the whole array, and doesn't know that the loop actually always executes at least once.

-Winitialized, by contrast, only warns when we can prove your program has a bug (or contains dead code).

There are a few improvements we could make to reduce the false positive rate here (some crude field sensitivity might be relatively straightforward to add), but we don't want to recreate the full intelligence of the clang static analyser here, and keeping this warning simple enough that we can run it as part of normal compilations is a goal.

我还在该报告中指出,即使其中一个数组成员明显未初始化,以下示例也没有给出警告:

#include <stdio.h>

typedef struct { int x[2]; } test_t;

test_t foo_3(void);

test_t foo_3() {
test_t t;
t.x[0] = 0;
return t;
}

int main() {
test_t t;

t = foo_3();
printf("%i %i\n", t.x[0], t.x[1]);
}

这让我得到了回复:

As I mentioned in comment#1, the analysis we currently perform cannot tell the difference between writing to one array element and writing to the whole array. In simple cases, this should be relatively straightforward to improve, so I think for that reason this bug is valid (but of low priority, given that this warning is expected to have false positives).

所以 -Wconditional-uninitialized 以给出误报而闻名。显然,静态分析器并不像我预期的那样彻底。我很惊讶在给出分析器似乎工作得更好的更复杂的场景之前我没有遇到过这样的事情,但正如@toohonestforthissite 在上面的评论中也指出的那样,通过像这样的结构按值传递数组不是在 C 中做的标准事情。

-Wno-conditional-uninitialized#pragma clang diagnostic ignored "-Wconditional-uninitialized" 应该为那些想要使用 -Weverything 的人消除警告 在这种情况下。

关于Clang -Wconditional-uninitialized on struct member array 赋值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52194930/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com