Reinier Torenbeek
Reinier Torenbeek

Reputation: 17373

How to detect or prevent uninitialized array elements at compile time?

The example below shows code using uninitialized array elements:

#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 generates a warning for val but not for 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.

The compiler probably concludes that str actually is initialized because the pointer itself has a value. It is just that its elements are not initialized. So the compiler is right.

On the other hand, the compiler explicitly decides not to insert any initialization of the elements here, so it is aware of the uninitialized elements in the array. Then why does it not warn about that?

Are there any compiler settings or other tools that can help to detect this at compile time? I am interested in any C-compiler, not just gcc.

Upvotes: 3

Views: 1392

Answers (2)

chux
chux

Reputation: 153338

Consider the following. The first printf() has well defined behavior even though the elements of str[] are not initialized. The next 2 have problems.

For a compiler to distinguish, it needs to analyze the code. As the C standard does not require this level of analysis, a compliant complier may have no ability to detect and thus no compiler settings.

Various tools and compilers do analyze code.

char str[10];
printf("<%.*s>\n", 0, str);
printf("<%.*s>\n", 1, str);
printf("<%s>\n", str);

Another approach is to code defensively. Simple initialize the array. A good compiler in the following case would detect the unnecessary initialization and optimize it out.

char str[10] = "";  // or = {0};
strcpy(str, "ABC");

Upvotes: 0

N. Leavy
N. Leavy

Reputation: 1074

I don't GCC will discover this kind of uninitialised buffer problem. There are static analysis tools that will attempt to do a better job of detecting uninitialised variables. Running split does detect that something is wrong, though it isn't the most informative message:

$ 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

Upvotes: 1

Related Questions