Zebrafish
Zebrafish

Reputation: 14318

Is there any way of finding out if the main() function of your program has been entered yet?

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

Answers (2)

Ahmed AEK
Ahmed AEK

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

alagner
alagner

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.

demo

Upvotes: 1

Related Questions