Question

Hi there in this question i read that compilation order doesn't matter but i have really odd situation.

I have few global variables in file CCSizePolicy.cpp They look like this:

const CCSizePolicy CCSizePolicyWrapContent ( Const::WRAP_CONTENT );
const CCSizePolicy CCSizePolicyMatchContent ( Const::MATCH_PARENT );
const CCSizePolicy CCSizePolicyZero ( Policy::SP, 0 );

in header

    enum Const
    {
        WRAP_CONTENT = -1, MATCH_PARENT = -2
    };

extern const CCSizePolicy CCSizePolicyWrapContent;
extern const CCSizePolicy CCSizePolicyMatchContent;
extern const CCSizePolicy CCSizePolicyZero;

Also in CCLayoutParams.h

extern const CCLayoutParams CCLayoutParamsMatchMatch;
extern const CCLayoutParams CCLayoutParamsWrapWrap;
extern const CCLayoutParams CCLayoutParamsMatchWrap;
extern const CCLayoutParams CCLayoutParamsWrapMatch;

and CCLayoutParams.cpp

const CCLayoutParams CCLayoutParamsMatchMatch ( CCSizePolicyMatchContent,
        CCSizePolicyMatchContent );

const CCLayoutParams CCLayoutParamsWrapWrap ( CCSizePolicyWrapContent,
        CCSizePolicyWrapContent );

const CCLayoutParams CCLayoutParamsMatchWrap ( CCSizePolicyMatchContent,
        CCSizePolicyWrapContent );

const CCLayoutParams CCLayoutParamsWrapMatch ( CCSizePolicyWrapContent,
        CCSizePolicyMatchContent );

So when i use them in my program i call CCLayoutParamsWrapWrap.getWidth() and CCLayoutParamsWrapWrap.getHeight()

This should output me -1 -1 BUT i have 0 0...

Order in makefile looks like this:

src/view/layout/CCLayoutParams.cpp\
...
src/view/CCSizePolicy.cpp\

when i change it to

src/view/CCSizePolicy.cpp\
src/view/layout/CCLayoutParams.cpp\
...

Everything starts working (i get -1 -1) what is going on?

Im using Linux with gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)

My whole project is bugged i don't know why because i sort my source files by name??!?!

Was it helpful?

Solution

Most likely, it is not the order the files are COMPILED, but actually the order they are LINKED (which is defined by the order you have your sources in, I expect) - g++ "collects" the global initialization of variables in the linking stage, and they are then processed in the order they were found. However, this just happens to be the "observed behaviour". Initialization between different compile units in C++ is undefined. You must not rely on it being in one way or another, there is absolutely nothing preventing g++ from changing the order that it puts the global initialization so that it is done in reverse order instead of the current order (because that makes the link process faster, or some other clever reason - or just "felt like it") - and they wouldn't even have to tell you that they have done so.

So, basically, if you have global objects, then you must either put them into a single source file ("globalobjects.cpp" or some such) to make them initialize in a defined order, or don't rely on one being initialized before another. Or rely on the vague definition that "currently the linker does things in the right order as long as I put my files in the right order".

OTHER TIPS

The order of initialization of globals in different source files is unspecified. As such it can depend on anything, including for example the order that the files are compiled.

In this case, if CCLayoutParamsWrapWrap is initialized before CCSizePolicyWrapContent, then its constructor will not see the value -1 set by the constructor of CCSizePolicyWrapContent. It will instead see the value 0 set by so-called "static initialization", which happens before "dynamic initialization" (that is, constructor calls).

I don't know specifically what about gcc is causing the difference, but I suspect it's the link order rather than the compile order that really matters. That's just a guess, though, if you care to confirm or refute it you can test. The important point is that you shouldn't rely on it, since it's not required to behave like that.

In C++11 I think you could fix this by making sure that CCSizePolicyWrapContent is a constexpr object with constexpr constructor. Otherwise you should read about the "static initialization order fiasco", and the various techniques available to impose constraints on the initialization order, and then choose one that suits your circumstance.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top