引用:
来自微软的"Best Practices for Creating DLLs"文档http://download.microsoft.com/download/a/f/7/af7777e5-7dcd-4800-8a0a-b18336565f5b/DLL_bestprac.doc :
"DLL 经常具有复杂的相互依赖关系,这些关系隐式地定义了它们必须被加载的顺序。库加载器有效地分析这些依赖关系,计算出正确的加载顺序,并按照该顺序加载 DLL。"[1]
"(在 DLLMain 内部) 使用来自动态 C 运行时 (CRT) 的内存管理函数。如果未初始化 CRT DLL,则对这些函数的调用可能导致进程崩溃。"[2]
来自 MSDN:http://msdn.microsoft.com/en-us/library/988ye33t.aspx
"_DllMainCRTStartup 函数会执行一些操作,包括调用 _CRT_INIT,该函数初始化 C/C++ 运行时库并在静态非局部变量上调用 C++ 构造函数。如果没有此函数,则运行时库将处于未初始化状态。"[3]
"除了初始化 C 运行时库之外,_DllMainCRTStartup 还调用一个名为 DllMain 的函数。"[4]
问题:
如果您的 DLL 依赖于 CRT DLL,则根据[1],CRT DLL 将首先被加载 (被初始化),因此[2]如何发生?
根据[3]和[4],_DllMainCRTStartup 将调用 _CRT_INIT 来初始化 CRT,那么[2]如何发生?
如果可执行文件通过"隐式链接"加载您的 DLL,则基于 [3] - _DllMainCRTStartup 调用 _CRT_INIT 来初始化 CRT,且 mainCRTStartup 也将初始化 CRT,那么 CRT 实际上会发生什么?
如果您的 DLL 将在 mainCRTStartup 之前被加载,则在 DLLMain 或其他导出函数内部调用 CRT 函数是否安全?
谁将实际初始化 CRT DLL?
---1. 如果 DLL 依赖于 CRT DLL,则 CRT DLL 最终会首先被加载,以确保正确的加载顺序和避免由于缺少所需的 DLL 而导致进程崩溃等问题。然而,如果 CRT DLL 未初始化,对 CRT 函数的调用可能会导致进程崩溃,因为此时 CRT 数据结构未初始化。
2. 在 DLLMain 中使用 CRT 的内存管理函数并不总是安全的,这是因为如果 CRT DLL 未初始化,那么 CRT 内部数据结构也未初始化,这将导致调用 CRT 函数时出现错误。因此,建议在 DLLMain 中避免使用 CRT 函数,或者确保 CRT DLL 已正确初始化。
3. 如果可执行文件通过"隐式链接"加载 DLL,则 _DllMainCRTStartup 将被优先调用以初始化 CRT,并在静态非局部变量上调用 C++ 构造函数。然后,操作系统将继续调用主程序入口点 (mainCRTStartup 或 WinMainCRTStartup) 来初始化 CRT,从而完成整个初始化过程。
4. 如果您的 DLL 将在 mainCRTStartup