【发布时间】:2012-12-12 03:03:12
【问题描述】:
从 MSDN 文档中可以看出,我们不应该在 DllMain 入口点函数中调用 LoadLibrary/FreeLibrary。
入口点函数应该只执行简单的初始化或 终止任务。它不能调用 LoadLibrary 或 LoadLibraryEx 函数(或调用这些函数的函数),因为这可能 在 DLL 加载顺序中创建依赖循环。这可能会导致 在系统执行其初始化代码之前使用的 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 中的错误。我们是 研究此错误并将在此处发布新信息 可用的 Microsoft 知识库。
【问题讨论】:
-
调用 ExitInstance() 时释放 DLL 毫无意义。无论如何,当进程终止时,DLL 将在几毫秒后自动卸载。
-
由于 CWinApp 是在主可执行文件中声明的,因此不会从 DllMain 调用其 ExitInstance(还有其他原因,因为可执行文件没有 DllMain)。因此,这个问题没有实际意义。
-
@RaymondChen,谢谢,我已经完善了我的问题,即 TestApp.dll 是动态链接到 MFC 的常规 DLL,因此调用 ExitInstance() 以响应 InternalDllMain 中的 DLL_PROCESS_DETACH 消息。跨度>
-
卸载TestApp.dll的调用栈已经贴在问题内了。