Oleksandr Shtykhno
Oleksandr Shtykhno

Reputation: 806

Static initialization in C++

Hi, all!

I'm developing winForm app on visual C++ (managed code). This app link native static library which contain block of code with static variable initialization:

Cls.h

class Cls
{
public:
    static Cls* getInstance();

private:
    static Cls _instance;
protected:
    Cls(void);
};

Cls.cpp

#include "StdAfx.h"
#include "Cls.h"

Cls::Cls(void)
{
}

Cls Cls::_instance;

Cls* Cls::getInstance()
{
    return &_instance;
}

I can link those library successfully, but when I try to use getInstance() method I get a run-time error before invoke main function of my app.

It's a third party library, so I cannot rebuild it or redefine Cls class on any other way.

App project uses /clr, entry point defined as main.

I tired to search a solution. I found that I must change entry point, but I don't know what value would be correct.

Please, help!

Upvotes: 1

Views: 848

Answers (1)

Mike Seymour
Mike Seymour

Reputation: 254561

You're encountering the notorious "static initialisation order fiasco". When static objects are defined in two translation units, it's unspecified which is initialised first; so, if the constructor of one refers to the other, you could end up accessing it before it is initialised. The only guarantee is that they will all be initialised before main begins.

The best solution is to avoid static objects. In particular, the Singleton anti-pattern that you are using is rather tricky to get right in C++, and is generally more trouble than it's worth.

If you really want to do this, then you can work around the fiasco by defining the static object inside a function:

Cls* Cls::getInstance()
{
    static Cls _instance;
    return &_instance;
}

This has the disadvantage that it introduces a "destruction order fiasco" (where it might not be safe to access from the destructor of another static object), and that it might not be thread-safe in some compilers (although it should be in any that claims C++11 compliance). If construction is thread-safe, then there will be a (small) runtime cost for each access, which might be a problem if you have extreme performance issues.

UPDATE: I've just noticed that you say that this evil class is outside your control and can't be changed. In that case, your options are:

  • Get rid of this library and use something less insane, or
  • Be careful not to access any of its static data until main has begun; in particular, follow my advice above and avoid any static objects of your own.

Upvotes: 4

Related Questions