3

I am porting a class to C++ and need to execute some initialization code before the first instance of my class is created; executing the code before main() gets control suits me. How to do it in C++?

kludg
  • 27,213
  • 5
  • 67
  • 118

6 Answers6

10

Initial answer

You could use a constructor of an object at namespace scope.

namespace {
struct Init
{
    Init()
    {
        // Initialization code here.
    }
} init_;
} // namespace

Beware, this has some limitations, especially on Windows. On Windows, the ctor is invoked with the loader lock held, thus you cannot do anything that would require loading DLLs and such. This includes initialization of WinSock because it can try to load external DLLs.

Update

According to some sources, you can work around this limitation by using QueueUserAPC. This technique has limitations as well, albeit different ones. I have used this and my experiments show that this only works if you are using Visual Studio and its C library as DLL, i.e., the MSVCRT.DLL, MSVCR100.DLL, etc. (/MD or /MDd switches)

Update 2

Here is a link to similar issue (mine, actually) with one important bit:

After some testing it seems that the APC method works if I queue the APC from DllMain() but it does not work if I queue the APC from a ctor of a static global instance of a class.

Community
  • 1
  • 1
wilx
  • 17,697
  • 6
  • 59
  • 114
  • 1
    you should use an unnamed namespace instead of static. As far as I know the usage of static is deprecated in this context (see http://stackoverflow.com/questions/154469/unnamed-anonymous-namespaces-vs-static-functions) – Tobias Langner Aug 12 '13 at 09:03
  • you could lazy-load via a factory. Then you don't run into the loader lock. – Tobias Langner Aug 12 '13 at 09:05
  • 1
    +1 for mentioning one limitation on Windows. Another limitation is that static initialization order is undetermined, so using this construction multiple times in a program may cause interesting issues. You could work around this with "lazy" initialization (e.g. in the object constructor: if(!initialized) initialize()...) – Joris Timmermans Aug 12 '13 at 09:06
  • I understand that testing `initialized` flag in ctor solves the problem. I am interested is it possible to do it without using the flag. – kludg Aug 12 '13 at 09:10
  • @MadKeithV if you work with factory-methods, you can easily resolve the order of creation. C++ guarantees that a static member of a function is initialized at first call. With C++ 11 I even think this is thread safe. – Tobias Langner Aug 12 '13 at 09:14
  • @TobiasLangner - yes that's what I always do if I absolutely cannot avoid static initialization somewhere. It's kindof what I meant with the "lazy" initialization, but I realize there's zero context in my previous comment to suggest that :-). – Joris Timmermans Aug 12 '13 at 09:30
2
struct Init
{
   Init() 
   {
      /* Your Initialization Code */
   }
} x;

int main()
{

}
P0W
  • 46,614
  • 9
  • 72
  • 119
2

Global and static classes are constructed before main() starts executing.

class hello {

    hello () { std::cout << "hello" << std::endl; }

};


hello hi;

int main(){
   std::cout << "hello again" << std::endl;
   return 0;

}

output will always be

hello
hello again

since the hello object instance is created before main starts since hi is a global instance of class hello

hetepeperfan
  • 4,292
  • 1
  • 29
  • 47
2

My answer addresses your real problem - performing one-time initialization before the first instance of your class, not executing before main.

Just use a static variable to make sure you execute the one time init code only once. Use synchronization if you need to be thread-safe, though it would have a performance hit.

class MyClass {
    MyClass() {
         // Perform the one-time initialization.
         static bool passed = false;
         if (!passed) {
             performOneTimeInitialization();
             passed = true;
         }

         // Continue with normal construction.
    }
};
sashoalm
  • 75,001
  • 122
  • 434
  • 781
  • Yes that is my current solution :) – kludg Aug 12 '13 at 09:16
  • 1
    +1 for using statics for what they're made for :-). Just a detail, but using an int as a flag is C-style, I think it's good practice to use booleans instead when writing C++ code. – halflings Aug 12 '13 at 09:17
  • You're right, `bool` would be more appropriate, I changed it to `bool`. – sashoalm Aug 12 '13 at 09:20
  • 1
    @user246408 Ah, you had already implemented it, but were looking for a better solution? In that case, I advise you to stick to your current code, because executing anything before `main()` is a hack, non-standard, and very probably unwise. The program is just not initialized properly before `main()`. – sashoalm Aug 12 '13 at 09:23
  • Note that thread safety code is added to initialization of local statics by some compilers (e.g. GCC). This has not only considerable overhead but, depending on the version, can also lead to [other nasty effects](http://stackoverflow.com/a/1514444/572743). I prefer to run code that should run "before" `main` inside `main`, as the very first thing. That just works, and there are no "ifs" and "whens". – Damon Aug 12 '13 at 09:38
  • 1
    He's creating a library to be used in third-party projects, though, so he might not have control over what goes in `main()`. He could always make it a requirement to initialize the library before using it, of course. – sashoalm Aug 12 '13 at 09:40
1

An additional solution to your real problem (using factory methods):

namespace 
{
    struct Initializer
    {
        Initializer()
        {
        /* initializing code goes here */
        }
    }
}

MyClass CreateMyClass()
{
    static Initializer init;
    return new MyClass();
}

The initializing code is executed the first time you call CreateMyClass. It should be even threadsafe with a C++11 compiler. If you don't have one and need the thread-safety, you can check boost::call_once.

Tobias Langner
  • 10,634
  • 6
  • 46
  • 76
1

You are in fact asking two different questions here, one describing the problem you want to solve:

I [...] need to execute some initialization code before the first instance of my class is created;

And the second is about how you think the problem can be solved:

executing the code before main() gets control suits me. How to do it in C++?

For that second question you already have one answer multiple times (the global variable). This can be a viable solution, although I'd prefer a private static class member to limit the visibility of that global variable:

class X {
  const static bool initialized;

};

//X.cpp:
namespace {
  bool preInitialization() {
    //your pre-main code here
    return true;
  }
}

bool X::initialized = preInitialization();

For the first question, you could delay the execution of the initialization code until right when the first variable of your class gets initialized:

class X {
  X();
};

//X.cpp:

namespace {
  bool preInitialization() {
    //your pre-main code here
    return true;
  }
}

X::X() {
  static bool b = preInitialization();
}

That way your code executes during the first constructor call of X. That may have some drawbacks, e.g. if the members of X can only be initialized after the initialization code has executed, or in the presence of multiple constructors. You can refine that method by pushing it into an empty base class:

class PreInit {
  static bool preInitialization() {
    //your pre-main code here
    return true;
  }
public:
  PreInit() {
    static bool b =preInitialization();
  }
};

class X : private PreInit {
  //normal class implementation
};

That way you can even execute the code before the first construction of any object of a number of classes, just by deriving all the classes in question from the PreInit class. It is only a better design to factor out the pre-initialization into a class of its own, obeying the SRP.

Arne Mertz
  • 24,171
  • 3
  • 51
  • 90