I am writing a DLL which defines a global static object.
In the object's constructor I am doing some initialization that may or may not succeed.
Is it possible to signal success or failure of the initialization process in DllMain() ? Which of the two is called first ?
Thank you.
Constructors for global objects from a single module are invoked in the order declared in the source code, but the relative order of objects from different object files is unspecified. Global constructors are called after initialization of other global variables and before the main() function is called.
Static objects are declared with the keyword static. They are initialized only once and stored in the static storage area. The static objects are only destroyed when the program terminates i.e. they live until program termination. A program that demonstrates static objects in C++ is given as follows.
MSDN's DllMain documentation says:
If your DLL is linked with the C run-time library (CRT), the entry point provided by the CRT calls the constructors and destructors for global and static C++ objects. Therefore, these restrictions for DllMain also apply to constructors and destructors and any code that is called from them.
Since the code within DllMain may use the static objects, the static objects must be constructed before DllMain is run for DLL_PROCESS_ATTACH, and destroyed after it is run for DLL_PROCESS_DETACH.
You can verify this with a simple test exe and test dll.
EXE:
int _tmain(int argc, _TCHAR* argv[])
{
wprintf(L"Main, loading library\n");
HMODULE h = LoadLibrary(L"Test.dll");
if (h)
{
wprintf(L"Main, freeing library\n");
FreeLibrary(h);
}
wprintf(L"Main, exiting\n");
return 0;
}
DLL:
struct Moo
{
Moo() { wprintf(L"Moo, constructor\n"); }
~Moo() { wprintf(L"Moo, destructor\n"); }
};
Moo m;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
wprintf(L"DllMain, DLL_PROCESS_ATTACH\n");
break;
case DLL_THREAD_ATTACH:
wprintf(L"DllMain, DLL_THREAD_ATTACH\n");
break;
case DLL_THREAD_DETACH:
wprintf(L"DllMain, DLL_THREAD_DETACH\n");
break;
case DLL_PROCESS_DETACH:
wprintf(L"DllMain, DLL_PROCESS_DETACH\n");
break;
default:
wprintf(L"DllMain, ????\n");
break;
}
return TRUE;
}
Together those will print:
Main, loading library
Moo, constructor
DllMain, DLL_PROCESS_ATTACH
Main, freeing library
DllMain, DLL_PROCESS_DETACH
Moo, destructor
Main, exiting
As you can see, the static object is constructed before DllMain(...,DLL_PROCESS_ATTACH,...)
and destroyed after DllMain(...,DLL_PROCESS_DETACH,...)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With