我发现了一个特定的使用模式,它看起来完全没问题,以前没有编译器抱怨过。现在它使用 gcc-11 发出警告:下面是一个接近最小的示例。另存为t.c
并使用gcc-11 -O2 -Wall -c t.c
.
#include <stdlib.h>
#include <string.h>
extern void f(const char *s);
void
t(int len, char *d)
{ char tmp[500];
char *s, *o;
int i;
if ( len <= sizeof(tmp) )
s = tmp;
else if ( !(s=malloc(len)) )
return;
for(o=s,i=0; i < len; i++)
*o++ = d[i]+1;
f(s);
// i = strlen(s);
if ( s != tmp )
free(s);
}
编译结果:
gcc-11 -O2 -Wall -c t.c
t.c: In function ‘t’:
t.c:20:3: warning: ‘s’ may be used uninitialized [-Wmaybe-uninitialized]
20 | f(s);
| ^~~~
t.c:4:13: note: by argument 1 of type ‘const char *’ to ‘f’ declared here
4 | extern void f(const char *s);
| ^
t.c:20:3: warning: ‘tmp’ may be used uninitialized [-Wmaybe-uninitialized]
20 | f(s);
| ^~~~
t.c:4:13: note: by argument 1 of type ‘const char *’ to ‘f’ declared here
4 | extern void f(const char *s);
| ^
t.c:8:8: note: ‘tmp’ declared here
8 | { char tmp[500];
| ^~~
现在有一些观察
- 调用 strlen(s) 而不是 f(s) 不会导致警告。请注意,两者都接受
const char*
(签入/usr/include/string.h
) - 如果我删除 的
const
声明中的f()
,问题也会消失。 - 调用 using
f((const char*)s)
也无济于事。 - 像 in 一样初始化 s
char *s = NULL
也无济于事(无论如何我都不希望这样做,因为它隐藏了有关未初始化变量的正确警告)。
我了解到,声称某事是 GCC 错误通常被正确地证明是错误的。所以我首先在这里检查我缺少什么。
编辑由于我无法在评论中添加代码,因此这里是反驳部分声明的代码。这编译得很好:
extern void f(const char *__s);
void
t(int len, char *d)
{ char tmp[500];
char *s=tmp, *o;
int i;
for(o=s,i=0; i < len; i++)
*o++ = d[i]+1;
f(tmp);
}