Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GCC - no warning about an uninitialized array with -O0

Tags:

c

gcc

My GCC 7.3.0 and 8.2.0 has some strange behavior I can't explain. This program, which obviously ends in a Segmentation fault:

int main()
{
    double array[2]={0, 0};
    printf("%f\n", array[999]);

    return 0;
}

Compiled with

gcc -Wall -O2 main.c

Produces the warning

main.c: In function 'main':
main.c:6:5: warning: 'array[999]' is used uninitialized in this function [-Wuninitialized]
     printf("%f\n", array[999]);
     ^~~~~~~~~~~~~~~~~~~~~~~~~~

But with optimization turned off:

gcc -Wall main.c

it produces no warning at all. My Code linter and Debug compile (gcc -g) uses -O0 and didn't pick up on a similar out of bounds error I made, until I compiled it as Release with Optimization turned on. Setting -O1 in the linter posts the warning as expected.

like image 756
FrostKiwi Avatar asked Mar 05 '23 16:03

FrostKiwi


1 Answers

This is a long-standing, documented limitation in GCC. Quoting the manual for GCC 3.0:

-Wuninitialized

Warn if an automatic variable is used without first being initialized or if a variable may be clobbered by a setjmp call.

These warnings are possible only in optimizing compilation, because they require data flow information that is computed only when optimizing. If you don't specify -O, you simply won't get these warnings.

The current version of the manual has actually removed the second paragraph of this quotation, saying instead "Because these warnings depend on optimization, the exact variables or elements for which there are warnings depends on the precise optimization options and version of GCC used." This is because, at some point between GCC 3.0 (released 2001) and GCC 8.2 (released 2018) the compiler was improved so that it will give warnings for at least some uses of uninitialized variables when not optimizing. For instance, the trivial test

int foo(void) { int x; return x; }

does provoke a warning when compiled with GCC 8.2 using -O0 -Wall.

It is worth pointing out that perfect diagnosis of uninitialized variables reduces to the infamous Halting Problem—which means it can't be done. You can implement a set of rules that are conservatively correct (they will detect all uses of uninitialized variables, but they may claim that some variables are used uninitialized when they aren't), e.g. Java's definite assignment rules, but that approach has historically been unpopular among C programmers. Given a demand for minimal false positives but also quick compilation when not optimizing, GCC's approach of doing more elaborate analysis when optimization is on is understandable.

like image 193
zwol Avatar answered Mar 10 '23 11:03

zwol