• Advertisement
Sign in to follow this  

[c++] Static variables not initialized if DllMain is user-defined (?)

This topic is 3506 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Let's say we have an executable called RuntimeLoader...
//RuntimeLoader.cpp

#include <windows.h>

typedef int (*fType)();

int main()
{
  SetCurrentDirectory("../../RuntimeLibrary/Debug");
  HMODULE hLib = LoadLibrary("RuntimeLibrary");
  int numberOfStaticsInitialized = 0;
  if (hLib) {
    fType fVal = reinterpret_cast<fType>(GetProcAddress(hLib, "func"));
    if (fVal) {
      numberOfStaticsInitialized = fVal();
    }
  }
  numberOfStaticsInitialized; // breakpoint here
  FreeLibrary(hLib);
  return 0;
}

...and a dynamic library called RuntimeLibrary...
//RuntimeLibrary.cpp

#include <windows.h>

//#include <_vcclrit.h> // UNCOMMENT TO INIT STATICS

extern "C"
{

// http://msdn.microsoft.com/en-us/library/ms682596(VS.85).aspx
BOOL WINAPI DllMain(
    HINSTANCE hinstDLL,  // handle to DLL module
    DWORD fdwReason,     // reason for calling function
    LPVOID lpReserved )  // reserved
{
    // Perform actions based on the reason for calling.
    switch( fdwReason ) 
    { 
        case DLL_PROCESS_ATTACH:
         // Initialize once for each new process.
         // Return FALSE to fail DLL load.
            //__crt_dll_initialize(); // UNCOMMENT TO INIT STATICS
            break;

        case DLL_THREAD_ATTACH:
         // Do thread-specific initialization.
            break;

        case DLL_THREAD_DETACH:
         // Do thread-specific cleanup.
            break;

        case DLL_PROCESS_DETACH:
         // Perform any necessary cleanup.
            //__crt_dll_terminate(); // UNCOMMENT TO DEADLOCK...
            break;
    }
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}

int n() // this is the "right" way to init statics, beside the ++
{
  static int sn = 0;
  return ++sn;
}

static int a = n(); // but sometimes we want some "special" behaviour
static int b = n();
static int c = n();
static int d = n();

int __declspec( dllexport ) func()
{
  return n();
}

}

Compiled and executed with the right path set, numberOfStaticsInitialized at "breakpoint here" is 5. Now set the dll entry-point (let's assume we need it) to our DllMain (RuntimeLibrary -> Properties -> Advanced -> Entry Point = DllMain), compile the lib and run the exe again. Now numberOfStaticsInitialized is 1! This indicates that a, b, c and d are not initialized :( Uncommenting the lines marked as "// UNCOMMENT TO INIT STATICS" makes it work again, but the use of _vcclrit is deprecated and seem to have something to do with managed code, something I would like to keep far (:P). Finally the explicit question(s): Is there a way to call the default DllMain from the user-defined one, or another way (other than using _vcclrit) to initialize static variables when the entry-point is user-defined? _vcclrit is bad? Thanks!

Share this post


Link to post
Share on other sites
Advertisement
You appear to be causing loader lock. This article might help.

http://msdn.microsoft.com/en-us/library/ms173266(vs.80).aspx

_vcclrit is deprecated because the /clr used to be able to deadlock as well (back in 2003). They've mostly fixed it though, afaik.

Share this post


Link to post
Share on other sites
It seem that deadlocks occur with managed code only, and I have not (I do not compile with /clr option).

I could fix this defining DllMain outside the extern "C" scope and removing DllMain from the /ENTRY.
From http://msdn.microsoft.com/en-us/library/3hxxtd06(VS.71).aspx :
Quote:
Note The Platform SDK documentation for DllEntryPoint says that the actual name of the entry-point function must be specified on the linker command line with the /ENTRY option. With Visual C++, you do not need to use the /ENTRY option if the name of your entry-point function is DllMain. In fact, if you do use the /ENTRY option and name your entry-point function something other than DllMain, the C run-time library will not get initialized properly.

This looks like a bug of VS2005 to me (even calling the entry-point as DllMain does not initialize the runtime properly).

Thanks anyway felisandria.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement