我们可以从ExitInstance调用FreeLibrary

从MSDN文档中我们可以看到,我们不应该在DllMain入口点函数中调用LoadLibrary / FreeLibrary。

入口点函数应该只执行简单的初始化或终止任务。 它不能调用LoadLibrary或LoadLibraryEx函数(或调用这些函数的函数),因为这可能会在DLL加载顺序中创build依赖关系循环。 这可能会导致在系统执行初始化代码之前使用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 – dynamic链接到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是从DllMain调用的(由堆栈跟踪确认),那么DllMain的所有规则都适用,包括禁止递归加载或卸载其他DLL。 (请注意,把你的CWinApp放在一个DLL中是非常不寻常的,MFC可能还有其他的问题,比如KB文章中提到的问题,并不是说有潜在或者没有更多的潜在问题,但是增加一个额外的注释警告。)