从MSDN文档中我们可以看到,我们不应该在DllMain入口点函数中调用LoadLibrary / FreeLibrary。
入口点函数应该只执行简单的初始化或 终止任务。它不能调用LoadLibrary或LoadLibraryEx 函数(或调用这些函数的函数),因为这可能 在DLL加载顺序中创建依赖循环。这可能导致a 在系统执行其初始化代码之前使用DLL。 同样,入口点函数也不能调用FreeLibrary 函数(或调用FreeLibrary的函数)在进程中 终止,因为这可能导致在之后使用DLL 系统已执行终止代码。
我的问题是:我们可以从ExitInstance()调用FreeLibrary吗?例如:
Test.exe - 主要可执行文件
HINSTANCE hDllMFC = LoadLibrary(L"TestApp.dll");
if (hDllMFC != NULL)
{
FreeLibrary(hDllMFC);
}
while unload the hDllMFC, the call stack looks like:
TestApp.dll!CTestAppApp::ExitInstance() Line 42 C++
TestApp.dll!InternalDllMain() Line 155 C++
TestApp.dll!DllMain() Line 272 C++
TestApp.dll!__DllMainCRTStartup() Line 512 C
TestApp.dll!_DllMainCRTStartup() Line 477 C
ntdll.dll!LdrpUnloadDll() Unknown
ntdll.dll!LdrUnloadDll() Unknown
KernelBase.dll!FreeLibrary() Unknown
Test.exe!wmain() Line 17 C++
TestApp.dll - 动态链接到MFC的常规DLL
CTestApp theApp;
HINSTANCE hDllResource = NULL;
BOOL CTestApp::InitInstance()
{
hDllResource = ::LoadLibrary(L"TestApp_Resource.dll");
return CWinApp::InitInstance();
}
int CTestApp::ExitInstance()
{
::FreeLibrary(hDllResource);
return CWinApp::ExitInstance();
}
TestApp_Resource.dll - 常规DLL,资源
...
我认为我们不应该,但是从CWinApp :: ExitInstance()的实现,我们可以看到,它也试图卸载资源dll。这是否意味着我们可以在ExitIntance()中调用FreeLibrary?
int CWinApp::ExitInstance()
{
//...
if (m_hLangResourceDLL != NULL)
{
::FreeLibrary(m_hLangResourceDLL);
m_hLangResourceDLL = NULL;
}
//...
}
我还在Win95中从ExitInstance调用FreeLibrary时发现了一个确认存在错误的文档。
BUG:从ExitInstance调用AfxFreeLibrary时断言 http://support.microsoft.com/kb/187684
状态:Microsoft已经确认这是Windows 95中的错误。我们是 研究这个bug并将在这里发布新信息 Microsoft知识库随时可用。
答案 0 :(得分:5)
实际上,如果从DllMain调用ExitInstance(由堆栈跟踪确认),则应用DllMain的所有规则,包括禁止以递归方式加载或卸载其他DLL。 (请注意,将您的CWinApp放入DLL中是非常不寻常的,MFC可能还有其他问题,例如知识库文章中提到的问题。并不是说潜在的问题有或没有,但添加了一个附加说明小心。)