Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which is called first, DllMain() or global static object constructor?

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.

like image 317
Wartin Avatar asked Dec 21 '10 04:12

Wartin


People also ask

What is a global constructor in C++?

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.

How do you declare a static object in C++?

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.


1 Answers

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,...)

like image 50
Leo Davidson Avatar answered Oct 11 '22 17:10

Leo Davidson