20
#include <iostream>

int main(int argc, char** args) {
  int foo = foo + 4;
  std::cout << foo << std::endl;
}

And a follow up question, is there a compiler flag to stop this sort of thing? I found -Wall works sometimes, better would be to prevent it entirely.

My compiler:  
g++ -v  
Using built-in specs.  
Target: i486-linux-gnu  
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.3-4ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu  
Thread model: posix  
gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)  
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Eric
  • 203
  • 2
  • 5
  • 1
    A compiler flag to stop what sort of thing? – tkerwin Mar 27 '11 at 16:46
  • 1
    What exactly is your question? Why don't you initialize foo? – mbx Mar 27 '11 at 16:46
  • `int foo = foo + 4;` doesn't mean anything. What did you mean when you wrote it? – David Heffernan Mar 27 '11 at 16:46
  • 6
    I don't know for sure, but I would guess that `int foo = foo + 4;` is undefined behavior, on account of reading the value of an uninitialized variable. – Björn Pollex Mar 27 '11 at 16:47
  • It was a bug from a program I wrote. And when I added -Wall, it didn't generate a warning. So basically I would like to know if I can stop it from happenning and out of curiosity, why it is even allowed. – Eric Mar 27 '11 at 16:48
  • -Wall works until you start using code that's not yours (and not from the standard library). -W4 tends to catch most of the ones you need and not others. – ssube Mar 27 '11 at 16:48
  • @Eric: Maybe [static analysis](http://stackoverflow.com/questions/141498/) can help. – Björn Pollex Mar 27 '11 at 16:56
  • Don't know for C++, but with code in plain C (or Objective-C) you can use LLVM compiler with static analyzer - it will warn you about using uninitialized variables. – kervich Mar 27 '11 at 18:59
  • So will gcc, but only if you specify -O or better. – Steve Jessop Mar 27 '11 at 19:02

5 Answers5

31

No there is no guaranteed way to stop this sort of thing. It is an integral part of C++ and C that the variable's name is visible in its initializer. It allows you to do such things as

T *t = malloc(sizeof(*t));

There is an issue report on the C++ issues list to require diagnostics in simple cases, but currently compilers are not required to diagnose your case.

It's also valid in a different context.

Edit: To clarify - the behavior of your snippet is undefined: You are reading the value of a not initialized variable. That compilers are not required to diagnose this does not mean that behavior is defined.

Community
  • 1
  • 1
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
7
int foo = foo + 4;

This is undefined behavior. Some compilers zero out automatically the space for local variables when others may not, so foo might contain stack's rubbish

BlackBear
  • 22,411
  • 10
  • 48
  • 86
3

I can bet this means undefined behaviour.

Edit: see the citation from answer to another question.

Edit: most probably, the value in the RHS is taken from uninitialized memory location in the stack, 4 is added to it and the result is used for initialization.

Community
  • 1
  • 1
Vlad
  • 35,022
  • 6
  • 77
  • 199
  • @Nawaz: this doesn't say what is wrong in the answer. BTW, the citation by the link I provided justifies the answer. – Vlad Mar 27 '11 at 16:53
  • @Vlad: Hmm.. you're right. I tried to undo my downvote, but for that you've to edit your post, because it's not letting me undo! – Nawaz Mar 27 '11 at 16:58
2

To get a warning from gcc for this particular code, you need -Wuninitialized (-Wall includes this) and -O (or any optimization level above 0).

The reason is that gcc can't diagnose use of uninitialized variables unless it does data flow analysis, and it doesn't do data flow analysis when optimization is disabled. And optimization is disabled by default.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
0

I would expect any half-way decent compiler to issue a warning for int foo = foo + 4; in its default configuration. Good ones will have options to reject it entirely as "use of uninitialised variable" and/or to accept any specific occurence of it where the programmer understands exactly what's going on and isn't concerned about unexpected behaviour.

I for example often used to write int toggle = toggle ^ 1 back in the days when compilers weren't so fussy, if all I wanted was a toggling switch where I didn't care whether it started TRUE or FALSE. Nowadays I'd probably write static bool toggle=TRUE; toggle=^toggle

FumbleFingers
  • 226
  • 5
  • 15