从 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 知识库中发布新信息,因为它可用。