The following code has a variable that may be uninitialized. It seems that gcc should be generating a warning but isn't:
$ cat a.c
int foo(int b) {
int a;
if (b)
a = 1;
return a;
}
$ gcc-4.7 -c -Wall -Wmaybe-uninitialized -o a.o ./a.c
$ gcc-4.7 -v
Using built-in specs.
COLLECT_GCC=gcc-4.7
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.7/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.7.3-2ubuntu1~12.04' --with-bugurl=file:///usr/share/doc/gcc-4.7/README.Bugs --enable-languages=c,c++,go,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.7 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.7 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --with-system-zlib --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.7.3 (Ubuntu/Linaro 4.7.3-2ubuntu1~12.04)
Any clues on how to get gcc to report the uninitialized variable?
An uninitialized variable has an undefined value, often corresponding to the data that was already in the particular memory location that the variable is using. This can lead to errors that are very hard to detect since the variable's value is effectively random, different values cause different errors or none at all.
Unlike some programming languages, C/C++ does not initialize most variables to a given value (such as zero) automatically. Thus when a variable is assigned a memory location by the compiler, the default value of that variable is whatever (garbage) value happens to already be in that memory location!
Warnings are diagnostic messages that report constructions that are not inherently erroneous but that are risky or suggest there may have been an error. The following language-independent options do not enable specific warnings but control the kinds of diagnostics produced by GCC.
The value in an uninitialized variable can be anything – it is unpredictable, and may be different every time the program is run. Reading the value of an uninitialized variable is undefined behaviour – which is always a bad idea.
It looks like you can't - see this bug report. (And this one, which is marked as a dupe of that one - it has an identical test case to yours.) Since it looks like the root-cause bug is almost 10 years old, it would seem it's not an easy problem to solve. In fact, the second bug I linked to has the phrase "Never going to be fixed" in the discussion, so that doesn't look good.
If it's really important to you, clang does catch this one with -Wsometimes-uninitialized
, which is included with -Wall
:
a.c:3:7: warning: variable 'a' is used uninitialized whenever 'if' condition is
false [-Wsometimes-uninitialized]
if (b)
^
a.c:5:10: note: uninitialized use occurs here
return a;
^
a.c:3:3: note: remove the 'if' if its condition is always true
if (b)
^~~~~~
a.c:2:8: note: initialize the variable 'a' to silence this warning
int a;
^
= 0
1 warning generated.
The problem is that gcc can't know you'll call the function with a zero argument. In this case, the fact that you're testing might be a good hint that you intend to sometimes do so, but the general case is much harder. Consider:
int foo(int b) {
int a;
switch(b) {
case 1:
a = 1;
break;
case 2:
a = 0;
break;
case 3:
a = 2;
break;
}
return a;
}
This would be a perfectly reasonable function whose interface contract is that you only pass 1, 2, or 3 to it, and any "uninitialized" warning would in that case be spurious, and thereby reduce the signal-to-noise ratio of the compiler's warning generation.
I agree it would be nice if compilers gave better diagnostics for things like this, but it's not easy, and warnings that can have false-positives are always a delicate balancing act between cluttering code with workarounds for the warnings and failing to catch bugs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With