>Scott Meyers describes a good technique for ensuring that static
>Objects are initialized in the correct order in "Effective C++".
>In the first edition it's item 47: "Ensure that global objects are
>initialized before they're used". The technique has been used by
>many implementations of the iostreams library (where it ensures
>that global objects like cin, cout and cerr are properly initialized
>before any code uses it, even if that code is in another static
>object). The technique relies on standard C++ behavior, so it
>works with almost any compiler. 
>
>The order in which static objects within a module are initialized
>can be controlled by declaring them all in the same source file
>in the appropriate order. The trick to ensuring that all the
>static objects in a module are initialized before you use them
>is to define a helper class for the module.
>
>So, in the header file <Module.h> we have:
>
>  // class defininitions for  module
>
>  // declarations for Module
>
>  // helper class to ensure static objects are initialized
>  // before they are used
>  class ModuleInit
>  {
>    private:
>      static unsigned int count;
>
>    public:
>      ModuleInit();
>      ~ModuleInit();
>  }
>
>  // declare a file static instance of ModuleInit()
>  static ModuleInit() module_init;
>
>Then in the implementation file for the module we have
>
>  // This will be initialized to zero before any constructors run
>  unsigned int ModuleInit::count;
>
>  ModuleInit::ModuleInit()
>  {
>    if (count++ == 0)
>    {
>        // initialize a static objects in Module
>    }
>  }
>
>  ModuleInit::~ModuleInit()
>  {
>    if (--count == 0)
>    {
>        // destroy static objects in Module
>    }
>  }
>
>As long as any code that uses objects defined in <Module.h> includes
>this header file before declaring its own static objects, all the
>static objects in <Module.h> will be initialized before they can
>be used.
>
>Stephen C. Steel

I knew about the trick of putting all static initializers in a library into 
single cpp file but there was a problem with initializers across libraries.

In my wxCommunicator, I use sipXtapi.dll and also link against sipxtacklib & 
sipxportlib statically (I use Url class directly).

This problem with static initializers can be easily demonstrated in 
wxCommunicator by making SipMessage::spSipMessageFieldProps statically 
initialized (not by new when certain method gets called)

SipMessage::SipMessageFieldProps SipMessage::spSipMessageFieldProps;

In that case, spSipMessageFieldProps is initialized twice, once inside dll, and 
2nd time in the exe. Initialization inside dll works fine, but in exe there was 
a nice crash in OsUtilWnt::synchObjAcquire, as rTimeout wasn't initialized yet 
(it was only initialized in dll).


So I used the approach you described and created a PortLib class which has 
static PortLib PortLib_init;

in the PortLib.h file outside the class, which means constructor will get 
called for every cpp file that includes it. Making it static is a nice trick, 
because it won't collide with other PortLib_init's in other cpp files. 
Constructor then looks like this:

PortLib::PortLib(void)
{
   if (count++ == 0)
   {
      OsTime::OS_INFINITY = new OsTime(0x7FFFFFFF,0x7FFFFFFF);
   }
}

I changed OS_INFINITY  type to pointer to OsTime and made all required changes 
in all libraries.

I included PortLib.h in OsUtilWnt.cpp and SipMessage.cpp (here it was needed as 
well)

After these changes, I didn't get a crash in OsUtilWnt::synchObjAcquire 
anymore, when I placed breakpoints I could see that this time OS_INFINITY was 
initialized properly.

This time it crashed in 
UtlLink* UtlLink::get()

as spLinkPool wasn't initialized yet, but this can be solved easily using the 
same technique. So we can use this approach and don't need to use any compiler 
dependent "tricks" (like #pragma init(lib) for MSVC) or init/shutdown methods.

Jaro
_______________________________________________
sipxtapi-dev mailing list
[email protected]
List Archive: http://list.sipfoundry.org/archive/sipxtapi-dev/

Reply via email to