0

During my work on bringing code from windows-only platform to the GNU compiler I noticed some strange behavior with an uninitialized pointer to a vector.

The corresponding code looks like this:

typedef vector<IPeer*> Network;
// [...]
Network* m_network;
// [...]
if (m_network == NULL)         // <-- this is the strange part
  m_network = new Network();  

The marked line is making me sad. After declaring my vector it was NULL when I compiled it on my Windows machine. After moving the code to my Mac using GNU Compiler (I'm compiling on g++-5 with -std=c++11) my vector doesn't seems to be NULL after declaration anymore. The marked line is skipped.

Is this an c++ standard implementation issue or where does this strange behavior came from?

Marschal
  • 173
  • 2
  • 11

2 Answers2

2

Uninitialized pointer has undetermined behaviour. Could be NULL or not, depending on the compiler (and, even for a specific compiler, Release and Debug binaries may have a different behaviour) and/or the memory state (see comments to this post).

It is recommended to always initialize them. Never expect an uninitialized variable to have a specific value (it's true for pointers, but also true for other types like int, bool that may take different default initialization values depending on the compiler/target).

It's actually hard to know what will be the value of an unitialized variable, and in many cases it is not deterministic.

jpo38
  • 20,821
  • 10
  • 70
  • 151
  • Ok, so it's really depending on the compiler. Thanks! – Marschal Dec 20 '15 at 17:49
  • 1
    @Marschal : Contrary to what jpo32 has stated, it does not depend on the compiler at all; it simply depends on what happens to be in that memory location when the variable is instantiated which in turn depends on the previous content of the stack, and there fore previously executed code. A change in any code that runs prior to this (including changes in code generation due to compiler options) could result in a change in behaviour. Zero is a value that occurs a lot in computing, so often the value just happens to be null - that's the "luck" part. – Clifford Dec 20 '15 at 21:08
  • 1
    @Clifford: It's perfectly legal for a compiler to generate code that initializes all uninitialized pointer to null -- or, more usefully, to some known invalid value like `(void*)0xDEADBEEF`. Also, uninitialized pointers with static storage duration (defined outside any function *or* with the `static` keyword) are initialized to null. – Keith Thompson Dec 20 '15 at 21:59
  • 1
    @KeithThompson : OK, instead of saying that *"it does not depend on the compiler at all"*, perhaps it would be better to caution that, *it may be compiler dependent, or it may be entirely non-deterministic*. In my observation of compilers (primarily in embedded systems), it is perhaps common for the *entire stack* to be initialised to some value, but implicit initialisation of individual local variables does not occur. Consequently, early in execution local variables have a deterministic value, but when that stack memory is reused, it has whatever was left there. – Clifford Dec 21 '15 at 07:56
  • Thanks to both of you for the clarification, I edited my post. – jpo38 Dec 21 '15 at 08:18
1

Local POD variables are initialised by implicitly. In your Windows implementation it just happened to be null by dumb luck and is dangerous code.

Use explicit initialisation:

Network* m_network = 0 ;
Clifford
  • 88,407
  • 13
  • 85
  • 165
  • Default initialization occurs, it's just that for POD objects, that means to leave the internal state as uninitialized. http://en.cppreference.com/w/cpp/language/default_initialization – Bill Lynch Dec 20 '15 at 17:33
  • @BillLynch : I changed the wording. I meant "not initialised by default" rather than "default initialisation" which of course has specific meaning in the language definition. – Clifford Dec 20 '15 at 21:00