在一个生成dll的工程中看到一个文件只有一句全局变量初始化的代码,很好奇为什么这句代码在dll加载的时候就会执行,因此断点调试发现
__declspec(noinline) BOOL __cdecl __DllMainCRTStartup( HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved ) { BOOL retcode = TRUE; __try { __native_dllmain_reason = dwReason; __try{ /* * If this is a process detach notification, check that there has * been a prior process attach notification. */ if ( (dwReason == DLL_PROCESS_DETACH) && (__proc_attached == 0) ) { retcode = FALSE; __leave; } if ( dwReason == DLL_PROCESS_ATTACH || dwReason == DLL_THREAD_ATTACH ) { if ( _pRawDllMain ) retcode = (*_pRawDllMain)(hDllHandle, dwReason, lpreserved); if ( retcode ) retcode = _CRT_INIT(hDllHandle, dwReason, lpreserved);//全局变量初始化,顺序貌似没有保证 if ( !retcode ) __leave; } retcode = DllMain(hDllHandle, dwReason, lpreserved);//dll入口函数,就是平时咋们在dll里写的 if ( (dwReason == DLL_PROCESS_ATTACH) && !retcode ) { /* * The user's DllMain routine returned failure. Unwind the init. */ DllMain(hDllHandle, DLL_PROCESS_DETACH, lpreserved); _CRT_INIT(hDllHandle, DLL_PROCESS_DETACH, lpreserved); if ( _pRawDllMain ) (*_pRawDllMain)(hDllHandle, DLL_PROCESS_DETACH, lpreserved); } if ( (dwReason == DLL_PROCESS_DETACH) || (dwReason == DLL_THREAD_DETACH) ) { if ( _CRT_INIT(hDllHandle, dwReason, lpreserved) == FALSE ) { retcode = FALSE ; } if ( retcode && _pRawDllMain ) { retcode = (*_pRawDllMain)(hDllHandle, dwReason, lpreserved); } } } __except ( __CppXcptFilter(GetExceptionCode(), GetExceptionInformation()) ) { retcode = FALSE; } } __finally { __native_dllmain_reason = __NO_REASON; } return retcode ; }
这就是dll加载过程中的部分代码,重点文字标红;因此可以发现全局变量在进入dllmain函数之前就要初始化了;
由此也可以延伸出一个问题,当全局变量初始化的时候相互依赖会造成bug,所以一个良好的设计是:
dll只有一个初始化类对象作为全局变量进行初始化,其他需要初始化的对象在这个初始化类里顺序初始化,这样就可以保证初始化的顺序了