我们可以从ExitInstance调用FreeLibrary吗?

ads*_*joh 6 windows dll mfc

从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++
Run Code Online (Sandbox Code Playgroud)

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();
}
Run Code Online (Sandbox Code Playgroud)

TestApp_Resource.dll - 常规DLL,资源

...

我认为我们不应该,但从CWinApp :: ExitInstance()的实现,我们可以看到,它也试图卸载资源DLL.这是否意味着我们可以在ExitIntance()中调用FreeLibrary?

int CWinApp::ExitInstance()
{
  //... 

 if (m_hLangResourceDLL != NULL)
  {
    ::FreeLibrary(m_hLangResourceDLL);
    m_hLangResourceDLL = NULL;
  }
  //...
}
Run Code Online (Sandbox Code Playgroud)

我还发现了一个文件,它确认在Win95中从ExitInstance调用FreeLibrary时存在错误.

BUG:从ExitInstance调用AfxFreeLibrary时断言 http://support.microsoft.com/kb/187684

状态:Microsoft已经确认这是Windows 95中的错误.我们正在研究此错误,并将在Microsoft知识库中发布新信息,因为它可用.

Ray*_*hen 5

如果实际上从DllMain调用了ExitInstance(由堆栈跟踪确认),则应用DllMain的所有规则,包括禁止以递归方式加载或卸载其他DLL.(请注意,将您的CWinApp放入DLL中是非常不寻常的,MFC可能还有其他问题,例如知识库文章中提到的问题.并不是说潜在的问题有或没有,但添加了一个附加说明警告.)

  • 好像FreeLibrary的行为在Win8中已被更改,这搞乱了MFC模块的状态,感谢您在MSDN论坛中查看相关问题[这里](http://social.msdn.microsoft.com/论坛/ EN-US /的WinForms /线程/ c872ae41-98e7-43ed-92e8-38f1d68bc5ed) (2认同)