5

Suppose I have the following files:

lib/A.h

#ifndef A_H
#define A_H

#include <vector>

class A {
        public:
                static int add( int x );
                static int size();
        private:
                static std::vector<int> vec;
};

#endif

lib/A.cpp

#include "A.h"

std::vector<int> A::vec;

int A::add( int x ) {
        vec.push_back( x );
        return vec.size();
}

int A::size() { 
        return vec.size();
}

lib/B.h

#ifndef B_H
#define B_H

class B {
        public:
                static const int val = 42;
};

#endif

lib/B.cpp

#include "B.h"
#include "A.h"

int tempvar = A::add( B::val );

and finally: main:cpp

#include <iostream>
#include "lib/A.h"
#include "lib/B.h"

int main() {
        std::cout << A::size() << std::endl;
}

The result of this code differs depending on how I compile it:

g++ main.cpp lib/A.cpp lib/B.cpp -o nolibAB
./nolibAB

prints "1"

g++ main.cpp lib/B.cpp lib/A.cpp -o nolibBA
./nolibBA

prints "0"

g++ -c lib/A.cpp lib/B.cpp
ar rvs lib.a A.o B.o
g++ main.cpp lib.a
./a.out

prints "0" (regardless if I reorder A.cpp and B.cpp)

Can someone tell me the reason that this is the case?

EDIT: I use gcc 4.6.1

fdlm
  • 614
  • 1
  • 5
  • 14
  • 2
    This question might be related: http://stackoverflow.com/q/211237/440558 – Some programmer dude Feb 07 '12 at 13:42
  • Well, they have to be initialised in _some_ order. Why are you surprised that the order of the modules has something to do with it, in this case? – Lightness Races in Orbit Feb 07 '12 at 14:08
  • I know about the (lack of a defined) static initialization order in C++. But since the static initialization of tempvar in B.cpp accesses (and modifies) A::vec, I would have thought that the program would crash if A::vec is modified without beeing initialized beforehand. So what happens here is that tempvar is initialized which adds a value to A::vec. Afterwards, A::vec is initialized which removes this value from the vector? – fdlm Feb 07 '12 at 14:16
  • This may vary by platform and version, you should be more specific than just "gcc". – Ben Voigt Feb 07 '12 at 14:18
  • If you write code based on any ordering you learn from this it's going to bite you back :p +1 for the interesting question though, I misread it to start. – John Humphreys Feb 07 '12 at 14:22

1 Answers1

1

This is undefined by the standard. Simply put: You should not rely on global variables being initialized in a certain order.

Related: Static initialization order issue in C++

Community
  • 1
  • 1
Johan Kotlinski
  • 25,185
  • 9
  • 78
  • 101
  • He didn't ask about the standard, he asked about additional guarantees provided by the GNU toolchain. – Ben Voigt Feb 07 '12 at 14:17
  • 2
    Not quite true -- global variables defined within a single compilation unit will be initialized in the order defined. The order is only undefined BETWEEN compilation units, which is the OP's example case. So one fix would be to gather all the globals into a single compilation unit and initialize them in a controlled order. – Chris Dodd Feb 07 '12 at 18:33
  • Thank you for the answer. Although it is not 100% correct, as pointed out by Chris Dodd, I will accept it. – fdlm Feb 08 '12 at 13:27