为什么我的 DLL 不需要 DllMain 函数?
Why does my DLL not require a DllMain function?
我刚刚将 C++ Windows DLL 项目添加到 Visual Studio (2022) 解决方案。向导在其中放了一个 DllMain
。这让我大吃一惊;我不记得我的其他 DLL 有 DllMain
函数;
搜索我的代码,发现我的 9 个 DLL 中 none 有 DllMain 函数。然而,它们都可以正常构建和工作。我检查了所有这些项目的项目设置:
- None 其中设置了链接器
/NOENTRY
选项。
- 他们都设置了
/SUBSYSTEM:WINDOWS
。
- None 其中设置了链接器
/NODEFAULTLIB
选项
- 肯定都是DLLS
所以我在刚刚添加的新项目中注释掉了那个DllMain。它仍然构建得很好。
我的知识显然已经过时了。我认为 DllMain
曾经是必需的。我记得几年前,当我未能添加 DllMain
.
时,我的 DLL 中出现了链接器错误
所以我的问题是:
- 为什么我的 DLL 不需要 DllMain?是否有一些构建设置我没有检查?
- 没有一个有什么缺点吗?
(注意这些DLLS都是export C++ 类。None其中是资源DLL,都已经运行6年了,有的使用了thread-local storage,有的它们在函数内部有静态变量。我一直认为使用这些东西需要一个 DllMain)
运行时库("CRT" = C/C++ 运行时库)提供 real DLL 入口点 _DllMainCRTStartup
,它可以执行初始化等操作调用 DllMain
之前的全局变量。 MSDN 上的文档对此进行了描述:
linker /ENTRY
选项的文档也相关:
您的 DllMain
也有一个 library-provided 弱符号,因此从实际入口点到 DllMain
的调用不会在 link 时因未解决的问题而失败外部的。来自上面的第一个文档:
By default, if you do not provide a DllMain
function, Visual Studio provides one for you and links it in so that _DllMainCRTStartup
always has something to call.
您提到的 thread-local 存储确实需要使用 library-provided 入口点;如果您使用 /ENTRY
选项到 link.exe 将库入口点替换为您自己的或 /NOENTRY
以禁用它,它们将会中断。 None 其中需要库入口点调用的 DllMain
完成任何操作。
我刚刚将 C++ Windows DLL 项目添加到 Visual Studio (2022) 解决方案。向导在其中放了一个 DllMain
。这让我大吃一惊;我不记得我的其他 DLL 有 DllMain
函数;
搜索我的代码,发现我的 9 个 DLL 中 none 有 DllMain 函数。然而,它们都可以正常构建和工作。我检查了所有这些项目的项目设置:
- None 其中设置了链接器
/NOENTRY
选项。 - 他们都设置了
/SUBSYSTEM:WINDOWS
。 - None 其中设置了链接器
/NODEFAULTLIB
选项 - 肯定都是DLLS
所以我在刚刚添加的新项目中注释掉了那个DllMain。它仍然构建得很好。
我的知识显然已经过时了。我认为 DllMain
曾经是必需的。我记得几年前,当我未能添加 DllMain
.
所以我的问题是:
- 为什么我的 DLL 不需要 DllMain?是否有一些构建设置我没有检查?
- 没有一个有什么缺点吗?
(注意这些DLLS都是export C++ 类。None其中是资源DLL,都已经运行6年了,有的使用了thread-local storage,有的它们在函数内部有静态变量。我一直认为使用这些东西需要一个 DllMain)
运行时库("CRT" = C/C++ 运行时库)提供 real DLL 入口点 _DllMainCRTStartup
,它可以执行初始化等操作调用 DllMain
之前的全局变量。 MSDN 上的文档对此进行了描述:
linker /ENTRY
选项的文档也相关:
您的 DllMain
也有一个 library-provided 弱符号,因此从实际入口点到 DllMain
的调用不会在 link 时因未解决的问题而失败外部的。来自上面的第一个文档:
By default, if you do not provide a
DllMain
function, Visual Studio provides one for you and links it in so that_DllMainCRTStartup
always has something to call.
您提到的 thread-local 存储确实需要使用 library-provided 入口点;如果您使用 /ENTRY
选项到 link.exe 将库入口点替换为您自己的或 /NOENTRY
以禁用它,它们将会中断。 None 其中需要库入口点调用的 DllMain
完成任何操作。