Reputation: 14318
I'm having some issues with static initialization order fiasco. I have a class that should not be instantiated/constructed before my program enters main. This is because when the program enters main all static initialisation has been completed. Obviously a simple answer is just don't instantiate/construct/initialise an object of that type as a static variable, but I want a check in case it happens accidentally and there's a bug I can't discover.
I thought about having a flag bHasEnteredMain that I can set as the first thing in main, but this doesn't help, because there's no initialization order and therefore that flag have the garbage equivalent to true at that memory, so it's of no use. Is there a way to do this? Is there an in-built flag or something like that in the C++ standard or the compiler that I can use as a check?
Upvotes: 2
Views: 138
Reputation: 18090
You can have a global bool that is set to false
, then you change it to true
in your main.
Global trivial objects are initialized before the C++ runtime starts initializing non-trivial objects on many platforms.
another solution is to have a meyers' singleton equivalent of a counter, that you call at the start of main and in the constructor of the class that you want to not construct statically.
int count()
{
static int counter = 0;
counter++;
return counter;
}
If this returns any number except 1 in main
then it was called during static initialization and a static instance of the class exists !
Upvotes: 3
Reputation: 4062
Function with a static flag inside (Meyers's singleton-like construct) is the way to go. Depending on what is needed, you can do it e.g. this way:
#include <iostream>
//yes, the interface is somewhat clunky
bool mainWasCalled(bool mark = false)
{
static bool wasCalled{};
if (!wasCalled && mark) {
wasCalled = true;
}
return wasCalled;
}
struct S
{
S() { std::cout << mainWasCalled() << '\n'; }
};
static S staticS;
S globalS;
int main()
{
mainWasCalled(true);
S localS;
}
Counter incremented in main
also could work, pick the interface you like.
This works based on the following principle:
static object inside function prevents the static initialization order fiasco -- it is initialized the moment the function is entered. The fuction itself effectively manipulates (and returns) the state of a global variable.
The only problem might occur when your global objects will try to call this function from within multiple threads; you can possibly have a data race between main()
and some other thread spawned before it's called.
Upvotes: 1