maolike

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

在一个生成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只有一个初始化类对象作为全局变量进行初始化,其他需要初始化的对象在这个初始化类里顺序初始化,这样就可以保证初始化的顺序了

posted on 2019-07-22 16:04  maolike  阅读(1916)  评论(0编辑  收藏  举报