首先调用的是 DllMain() 还是全局静态对象构造函数?

Posted

技术标签:

【中文标题】首先调用的是 DllMain() 还是全局静态对象构造函数?【英文标题】:Which is called first, DllMain() or global static object constructor? 【发布时间】:2011-05-28 15:06:36 【问题描述】:

我正在编写一个定义全局静态对象的 DLL。

在对象的构造函数中,我正在做一些可能会或可能不会成功的初始化。

是否可以在 DllMain() 中指示初始化过程的成功或失败?两者中哪个先调用?

谢谢。

【问题讨论】:

【参考方案1】:

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,...)之后销毁

【讨论】:

以上是关于首先调用的是 DllMain() 还是全局静态对象构造函数?的主要内容,如果未能解决你的问题,请参考以下文章

java中的全局变量和静态变量是在编译时分配内存还是在加载时分配内存??

静态static怎么理解,我只知道静态方法是不用实例化对象,可以直接用对象.方法调用,还有静态啥东东

c++ 全局静态函数的理解

C++ - 全局静态对象和局部静态对象的构造函数调用不同?

unity3D 封装全局更新函数

静态变量赋值问题