c++ - 是在 C++ 静态初始化之前还是之后调用 DllGetClassObject
问题描述
我有一个加载到 Microsoft 管理控制台 (MMC) 中的 DLL。似乎它的DllGetClassObject
函数正在调用第三方库的一些初始化函数,该函数已知依赖于静态初始化才能完成(因此main()
在常规 C++ 程序中之前不能调用它)。此功能似乎失败,并且管理单元未显示在 MMC 中。奇怪的是,如果我从 MMC 中删除它并再次添加它,它会成功加载。
关于 C++ 静态初始化在 DLL 中发生的确切时间(在回调之前和之后)的信息似乎很少,微软似乎已经删除了它的“DLL 最佳实践”论文,该论文在处理这种类型的许多答案和文章中被引用问题。
在任何地方(最好在 MSDN 上)是否有关于 C++ 静态初始化和 DLL 回调顺序的一些权威信息?
(我已经尝试过https://docs.microsoft.com/en-us/windows/desktop/api/combaseapi/nf-combaseapi-dllgetclassobject,我希望这会被记录在案)
编辑:将有问题的函数调用从DllGetClassObject
to移动DllMain
似乎可以解决问题。不过,仍在寻找权威文档。
编辑:从这个结果和答案得出结论,我在使用第三方初始化函数时遇到的问题不可能是由静态初始化引起的,因为静态初始化应该在之前完成DllMain
,因此也在之前完成DllGetClassObject
。
解决方案
在不宽恕或避免在 DLL 中使用 C++ 对象作为全局变量/静态变量的情况下,这里是您正在寻找的信息。操作顺序为:
- C/C++ 全局/静态初始化
DllMain
DllGetClassObject
这里的文档描述了 C/C++ 全局/静态初始化和DllMain
.
...当链接到 DLL 时,VCRuntime 代码提供了一个内部 DLL 入口点函数,称为
_DllMainCRTStartup
处理 Windows 操作系统消息到 DLL 以附加到进程或线程或从进程或线程分离。该_DllMainCRTStartup
函数执行基本任务,例如堆栈缓冲区安全设置、C 运行时库 (CRT) 初始化和终止,以及调用静态和全局对象的构造函数和析构函数。_DllMainCRTStartup
还调用其他库(如 WinRT、MFC 和 ATL)的挂钩函数来执行它们自己的初始化和终止。如果没有此初始化,CRT 和其他库以及您的静态变量将处于未初始化状态......在进程附加时,该
_DllMainCRTStartup
函数设置缓冲区安全检查,初始化 CRT 和其他库,初始化运行时类型信息,初始化和调用静态和非本地数据的构造函数,初始化线程本地存储,递增内部每个附加的静态计数器,然后调用用户或库提供的DllMain
...
您可以通过在您的中设置断点DllMain
然后查看导致DllMain
被调用的堆栈帧来自己查看所有这些。你会发现很多有趣的事情在你DllMain
被调用之前就已经完成了。
至于DllGetClassObject
:这个导出的函数不是魔法调用的。该函数的调用者必须做 3 件事 - 加载您的 DLL(例如,LoadLibrary
),查找从 DLL 加载的函数的地址(例如,GetProcAddress
),然后使用已知的DllGetClassObject
实现签名调用该地址。您可以手动完成所有这些操作,但像CoCreateInstance
自动按照此处描述的顺序执行这三件事的功能。DllMain
被调用时自动LoadLibrary
调用,直到返回LoadLibrary
后才DllMain
返回。如果DllMain
返回成功代码,则调用者LoadLibrary
将收到HMODULE
DLL 的。如果DllMain
返回一个错误代码,调用者将永远不会有一个HMODULE
DLL (LoadLibrary
将返回NULL
),因此调用者甚至找不到您的DllGetClassObject
函数,更不用说调用它了。
推荐阅读
- angular - 没有 TypeScript 的 Angular 8 依赖注入?
- angular - Angular translate core - 从 http 请求更新翻译
- android - 按钮上不显示可绘制图标
- c - yylval 在 lex 和 yacc 中的作用
- python - 回归与分类可以解决的问题
- java - 将罐子(多个)添加到 maven 类路径会产生错误
- python - python3:从编译模式中提取IP地址
- python - 为什么线性回归只对一个特征起作用,而对另一个特征起作用
- unix - 如何在 UNIX 中删除特定列的空格
- javascript - 如何更改我的代码以能够计算不同的 url 而不是当前页面