2

I have a problem with static members of a class not being initialized before the constructor. Am i doing something wrong? Is it a bug in G++ ? Any workarounds?

g++ --version : (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
I am also using Eclipse as my IDE, but i just copy the static lib headers to /usr/include/StaticTestLib/InitTest.h and the library to /usr/lib/x86_64-linux-gnu/libStaticTestLib.a

Note this only happens if the object that holds the data is defined before main and the class is in a Static Library.

Static library header (the static library itself is named StaticTestLib):

InitTest.h
#include <iostream>
namespace StaticTestLib  {
    class notifier_header{
    public:
        notifier_header(){
            std::cout<<"static var init"<<std::endl;
        }
    };

    class InitTest {
    public:
        static notifier_header _header_notifier;
        InitTest();
        virtual ~InitTest();
    };    
}

Static library source file:

InitTest.cpp
#include "InitTest.h"

namespace StaticTestLib  {
    notifier_header InitTest::_header_notifier;

    class notifier_cpp{
    public:
        notifier_cpp(){
            std::cout<<"code before constructor"<<std::endl;
        }
    }_notifier_in_cpp;

    InitTest::InitTest() {
        std::cout<<"constructor"<<std::endl;
    }

    InitTest::~InitTest() {
        std::cout<<"destructor"<<std::endl;
    }
}

This program:

StaticTest.cpp
#include <iostream>
#include <StaticTestLib/InitTest.h>

StaticTestLib::InitTest test;

int main() {
    std::cout << "program main" << std::endl;
    std::cout << "program end" << std::endl;
    return 0;
}

… outputs:

constructor
static var init
code before constructor
program main
program end
destructor

But this program:

#include <iostream>
#include <StaticTestLib/InitTest.h>

int main() {
    std::cout << "program main" << std::endl;
    StaticTestLib::InitTest test;
    std::cout << "program end" << std::endl;
    return 0;
}

… outputs:

static var init
code before constructor
program main
contructor
program end
destructor
Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
Mattahy
  • 23
  • 4

1 Answers1

2

My guess is that this is related to the order of static objects initialisation in different compilation units being undefined.

The second code snippet where you create a test object in your main is easy to explain. Static initialisation will always happen before any code is executed, so by the time you enter main, your notifier_header object is definitely created.

Now, when you create your test before main, you have two static objects. notifier_header object does not depend on your InitTest: it is scoped within that class, but it is stored in static memory. You seem to reference the notifier_header in your InitTest.cpp, which is a different compilation unit to main. A compiler is free to do static allocations in any order for those two units, provided that there is no interdependencies.

If your constructor depended on notifier_header, you could use it as a singleton. Create a function that returns an instance of a static object (headerInstance in the example below), and upon its call, the object will be created:

#include <iostream>
namespace StaticTestLib  {
class notifier_header{
public:
    notifier_header(){
        std::cout<<"static var init"<<std::endl;
    }
};


class InitTest {
public:
    InitTest();
    virtual ~InitTest();
    notifier_header& headerInstance();
};

}

Static library source file (InitTest.cpp)

#include "InitTest.h"

namespace StaticTestLib  {

class notifier_cpp{
public:
    notifier_cpp(){
        std::cout<<"code before constructor"<<std::endl;
    }
}_notifier_in_cpp;

InitTest::InitTest() {
    headerInstance();
    std::cout<<"constructor"<<std::endl;
}

InitTest::~InitTest() {
    std::cout<<"destructor"<<std::endl;
}

notifier_header& InitTest::headerInstance() {
    static notifier_header _header_notifier; // will only be constructed once
    return _header_notifier;
}

}

The output I get:

static var init
constructor
code before constructor
program main
program end
destructor
Maksim Solovjov
  • 3,147
  • 18
  • 28
  • But what if i need notifier_header initialized inside InitTest constructor? – Mattahy Aug 19 '15 at 16:44
  • It won't, it will just crash (this is just a small example, i have experienced this inside my project and I am stuck at this) – Mattahy Aug 19 '15 at 16:47
  • Well by making headerInstance() not static makes it not accesable inside a static method. I am testing making it static. (inside my real project) EDIT: It doesn't seem to crash, but some stuff doesn't work, looking into it. – Mattahy Aug 19 '15 at 17:20
  • 1
    Ok, got it to work in my project, just had to make method headerInstance() static. (and fix some other bugs) Thanks. – Mattahy Aug 19 '15 at 17:32