下面的示例显示了使用未初始化数组元素的代码:
bets_gambler_bet
#include <stdio.h>
int main(void)
{
char str[10]; /* elements not initialized */
int val; /* variable not initialized */
printf("%s\n", str); /* no warning */
printf("%d\n", val); /* warning */
return 0;
}
会针对gcc
生成警告,但不会针对val
生成警告:
str
编译器可能会得出结论$ gcc -Wall -c uninitialized.c
uninitialized.c:9:20: warning: variable 'val' is uninitialized when used here [-Wuninitialized]
printf("%d\n", val); /* warning */
^~~
uninitialized.c:6:12: note: initialize the variable 'val' to silence this warning
int val; /* variable not initialized */
^
= 0
1 warning generated.
实际 已初始化,因为指针本身有一个值。只是它的元素没有被初始化。所以编译器是对的。
另一方面,编译器明确决定不在此处插入元素的任何初始化,因此它知道数组中未初始化的元素。那为什么不警告呢?
是否有任何编译器设置或其他工具可以帮助在编译时检测到这一点?我对任何C编译器感兴趣,而不仅仅是str
。
答案 0 :(得分:1)
我不会GCC会发现这种未初始化的缓冲问题。有一些静态分析工具可以更好地检测未初始化的变量。运行split确实检测到出现了问题,尽管它不是最具信息性的消息:
$ splint quick.c
Splint 3.1.2 --- 03 May 2009
quick.c: (in function main)
quick.c:8:20: Passed storage str not completely defined (*str is undefined):
printf (..., str, ...)
Storage derivable from a parameter, return value or global is not defined.
Use /*@out@*/ to denote passed or returned storage which need not be defined.
(Use -compdef to inhibit warning)
quick.c:9:20: Variable val used before definition
An rvalue is used that may not be initialized to a value on some execution
path. (Use -usedef to inhibit warning)
Finished checking --- 2 code warnings
答案 1 :(得分:0)
请考虑以下事项。即使printf()
的元素未初始化,第一个str[]
也有明确定义的行为。接下来的两个有问题。
要使编译器区分,需要分析代码。由于C标准不需要这种级别的分析,因此兼容的编译器可能无法检测,因此也没有编译器设置。
各种工具和编译器都会分析代码。
char str[10];
printf("<%.*s>\n", 0, str);
printf("<%.*s>\n", 1, str);
printf("<%s>\n", str);
另一种方法是防御性编码。简单初始化数组。在以下情况下,一个好的编译器会检测到不必要的初始化并对其进行优化。
char str[10] = ""; // or = {0};
strcpy(str, "ABC");