我想写一个DLL,我希望在这个DLL被加载时,自动去加载另一个DLL,然后获得那个DLL里面的某个函数的地址,然后在我的DLL里面用。HINSTANCE hDll=0;
typedef int (WINAPI *lpFUNC)(CALCINFO* );
lpFUNC kxian=0;BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
 )
{
    switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
if (!hDll)
{
HINSTANCE hDll = LoadLibrary("chzhshch.dll");
}
else
{
lpFUNC kxian = (lpFUNC)GetProcAddress(hDll, "kxian");
}
}
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
{
if (hDll)
{
FreeLibrary(hDll);
}
}
break;
    }
    return TRUE;
}请问我的代码有什么问题呢?

解决方案 »

  1.   

    MSDN建议:It is not safe to call LoadLibrary from DllMain. For more information, see the Res section in DllMain.DllMain中调用LoadLibrary是不安全的,要么开线程加载,要么在需要调用kxian函数的时候加载。
      

  2.   

    MSDN里对这个问题的答案十分的晦涩。不过现在我们已经有了足够的知识来解答这个问题。
    考虑下面的情况:
           (a)DllB静态链接DllA 
           (b)DllB在DllMain里调用DllA的一个函数A1()
           (c)DllA在DllMain里调用LoadLibrary("DllB.dll")分析:当执行到DllA中的DllMain的时侯,DllA.dll已经被映射到进程地址空间中,已经加入到了module list中。当它调用LoadLibrary("DllB.dll")时,首先会调用LdrpMapDll把DllB.dll映射到进程地址空间,并加入到InLoadOrderModuleList中。然后会调用LdrpLoadImportModule(...)加载它引用的DllA.dll,而 LdrpLoadImportModule会调用LdrpCheckForLoadedDll检查是否DllA.dll已经被加载。 LdrpCheckForLoadedDll会在哈希表LdrpHashTable中查找DllA.dll,而显然它能找到,所以加载DllA.dll这一步被成功调过。DllA在它的DllMain函数里能成功加载DllB,并要执行DllB的DllMain函数对其初始化。站在DllB的角度考虑,当程序运行到它的DllMain的时侯,它完全有理由相信它隐式链接的DllA.dll已经被加载并且成功地初始化。可事实上,此时DllA只是处在"正在初始化"的过程中!这种理想和现实的差距就是可能产生的Bug的根源,就是禁止在DllMain里调用LoadLibrary的理由!
      

  3.   

    在DllMain中最好不要用LoadLibrray,容易造成死锁