Что называется первым, DllMain () или конструктор глобального статического объекта? - PullRequest
14 голосов
/ 21 декабря 2010

Я пишу DLL, которая определяет глобальный статический объект.

В конструкторе объекта я выполняю некоторую инициализацию, которая может или не может быть успешной.

Можно ли сигнализировать об успешном или неудачном процессе инициализации в DllMain ()? Какой из двух назван первым?

Спасибо.

1 Ответ

26 голосов
/ 24 декабря 2010

MSDN DllMain документация гласит:

Если ваша DLL связана с библиотекой времени выполнения C (CRT), точка входа, предоставляемая CRT, вызывает конструкторы идеструкторы для глобальных и статических объектов C ++.Следовательно, эти ограничения для DllMain также применяются к конструкторам и деструкторам и любому коду, который вызывается из них.

Поскольку код в DllMain может использовать статические объекты, статические объекты должны быть созданы до того, как DllMain будетзапустить для DLL_PROCESS_ATTACH и уничтожить после запуска для DLL_PROCESS_DETACH.

Вы можете проверить это с помощью простого тестового exe и теста 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;
}

Вместе они напечатают:

Main, loading library
Moo, constructor
DllMain, DLL_PROCESS_ATTACH
Main, freeing library
DllMain, DLL_PROCESS_DETACH
Moo, destructor
Main, exiting

Как видите, статический объект создается до DllMain(...,DLL_PROCESS_ATTACH,...) и разрушается после DllMain(...,DLL_PROCESS_DETACH,...)

...