Why uninitialized instead of out-of-bounds?

  • A+
Category:Languages

In the code below why is b[9] uninitialized instead of out-of-bounds?

#include <stdio.h>  int main(void) {     char b[] = {'N', 'i', 'c', 'e', ' ', 'y', 'o', 'u', '!'};     printf("b[9] = %d/n", b[9]);      return 0; } 

Compiler call:

% gcc -O2 -W -Wall -pedantic -c foo.c foo.c: In function ‘main’: foo.c:6:5: warning: ‘b[9]’ is used uninitialized in this function [-Wuninitialized]      printf("b[9] = %d/n", b[9]); % gcc --version gcc (Ubuntu 5.4.0-6ubuntu1~16.04.6) 5.4.0 20160609 Copyright (C) 2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

Update: Now this is odd:

#include <stdio.h>  void foo(char *);  int main(void) {     char b[] = {'N', 'i', 'c', 'e', ' ', 'y', 'o', 'u', '!'};     foo(&b[9]);     foo(&b[10]);     printf("b[9] = %d/n", b[9]);     printf("b[10] = %d/n", b[10]);      return 0; } 

Compiling this results in the warnings one would expect:

% gcc -O2 -W -Wall -pedantic -c foo.c foo.c: In function ‘main’: foo.c:9:5: warning: array subscript is above array bounds [-Warray-bounds]      foo(&b[10]);      ^ foo.c:10:29: warning: array subscript is above array bounds [-Warray-bounds]      printf("b[9] = %d/n", b[9]);                              ^ foo.c:11:29: warning: array subscript is above array bounds [-Warray-bounds]      printf("b[10] = %d/n", b[10]); 

Suddenly gcc sees the out-of-bounds for what it is.

 


I believe this could be the case here: in the first code, GCC notices that you don't need the entire char array at all, just b[9], so it can replace the code with

char b_9; // = ??? printf("b[9] = %d/n", b_9); 

Now, this is a completely legal transform, because as the array was accessed out of bounds, the behaviour is completely undefined. Only in latter phase does it then notice that this variable, which is a substitute for b[9], is uninitialized, and issues the diagnostics message.

Why I believe this? Because if I add just any code that will reference the array's address in memory, for example printf("%p/n", &b[8]); anywhere, the array now is fully realized in memory, and compiler will diagnose array subscript is above array bounds.


What I find even more interesting is that GCC does not diagnose out-of-bounds access at all unless optimizations are enabled. This would again suggest that whenever you're writing a program new program you should compile it with optimizations enabled to make the bugs highly visible instead of keeping them hidden with debug mode ;)

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: