如何在编译时检测或阻止未初始化的数组元素?

时间:2015-11-30 15:39:05

标签: c arrays static-analysis

下面的示例显示了使用未初始化数组元素的代码:

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

2 个答案:

答案 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");