在 MFC 应用程序中未调用 ExitInstance
Posted
技术标签:
【中文标题】在 MFC 应用程序中未调用 ExitInstance【英文标题】:ExitInstance not called in MFC app 【发布时间】:2010-07-06 14:12:21 【问题描述】:直到现在,我从来没有真正需要我正在开发的大型 MFC(如果重要的话是单文档界面)应用程序的 Winapp ExitInstance()。但现在我这样做了,主要是为了清理内存分配、卸载一些 DLL 等。好吧,我很快就从明显的内存泄漏中了解到,并且没有调用 ExitInstance。我错过了什么明显的东西吗?我是否需要手动向消息映射中添加一些内容以确保调用了我的 ExitInstance 覆盖?
我想我可以在其他地方进行清理,但如果我可以让它运行,那是最好的地方。有趣的是,我通过在 Google 中输入诸如“ExitInstance never call”之类的字符串,发现了很多这样的例子,但在任何情况下都没有提供任何真正的答案。当有人从文件菜单中单击关闭框或“退出”时,应用程序通常会关闭,并且主机窗口的 OnClose() 肯定总是会被调用。我什至尝试通过放置 AfxGetMainWnd()->DestroyWindow();在那个大型机 OnClose() 事件中,但我仍然无法让 ExitInstance() 实际运行。也许这只是一个很大的虚拟功能?或者也许 I'M 只是一个大傻瓜? :-)
【问题讨论】:
如果您的应用程序是从 CWinApp 派生的,则应始终调用 ExitInstance。如果没有,可能是没有正确声明,或者您的应用因某种原因提前终止。 我知道它应该,但它没有,即使没有运行、没有命中、没有错误,并且应用程序以代码 0 关闭。奇怪。我需要在消息映射中添加一些内容吗?如果我的 ExitInstance() 覆盖也是虚拟的(没关系),这是否重要。我是否需要在 Message 映射中添加一些东西以确保它被调用? “我的 ExitInstance() 覆盖是否也是虚拟的是否重要(不应该重要)。”这无关紧要,因为被覆盖的虚函数始终是虚函数,无论您是否将其标记为虚函数。 【参考方案1】:我遇到了和你类似的问题......我的问题是由 Unicode 和 MBCS 构建代码混合引起的......也许这是你的根本原因?
我必须将 MBCS 应用程序转换为 Unicode,但不可能转换整个项目,所以我不得不混合 Unicode 编译(应用程序)和 MBCS 编译代码(DLL)。
一些 MBCS DLL 是 MFC 扩展 DLL,其他是常规 DLL。
其中一个 MFC 扩展 DLL 包含资源(位图图像列表和常用对话框)。
我没有将 DLL 转换为 UNICODE,因为它有很多依赖的 DLL,这些 DLL 也必须进行转换,此外,我不需要常用对话框中的控件来支持 Unicode 文本。
所以我将 DLL 保留为 MBCS,并在使用 MBCS DLL 中使用资源的任何类之前使用 AfxSetResourceHandle .....这是为了使资源直接从 DLL 中提取,而不是通过 MFC 资源链,否则 MFC 无法找到非 unicode 资源。
我猜 MFC 不喜欢混合 Unicode 和包含资源的非 Unicode 编译代码.....在资源链中查找失败(我猜与资源 ID 的转换有关到一个 ID 字符串,即通过 MAKEINTRESOURCE)。
我制作了主应用程序 UNICODE,并确保 MBCS DLL 中类的 C++ 标头在函数原型中使用 CStringA,或者接受宽字符串并在内部进行转换。
我发现我的应用程序无法正常退出...它将停留在 MFC CWinThread::PumpMessage/AfxInternalPumpMessage() 调用中,并且永远不会调用 ExitInstance。
为了解决这个问题,在我的 CMainFrame::OnDestroy() 中,我将以下内容作为最后两条语句:
void CMainFrame::OnDestroy()
....
CFrameWnd::OnDestroy();
AfxPostQuitMessage(0);
【讨论】:
【参考方案2】:我遇到了同样的问题。原来它是由 CWinApp 对象在大型机被销毁后预翻译的一些消息引起的。它会在该处理过程中进行一些有效性检查,然后退出而不是通过正常的退出实例退出。
覆盖应用程序的 PreTranslate 消息并在没有主机时立即返回解决了问题。
BOOL CYourAppClass::PreTranslateMessage( MSG* pMsg )
// If the main window has gone away there is no need to do pre-translation.
// If the pre-translation were allowed to proceed the
// CWinAppEx::PreTranslateMessage may bail out without calling
/// the app's ExitInstance nor destructing the app object.
if ( !m_pMainWnd )
return FALSE;
return CWinAppEx::PreTranslateMessage( pMsg );
【讨论】:
【参考方案3】:您说“大型机窗口的 OnClose() 肯定总是被调用”。我的一个 MFC 应用程序有问题;我在窗口的 OnClose() 事件处理程序中放入了一些线程清理代码,但它没有被调用。经过一番痛苦,我将线程清理代码放入 OnDestroy() 事件处理程序中,现在它总是被调用。所以你可能想检查你的 OnClose() 事件处理程序是否总是被调用。
【讨论】:
【参考方案4】:我遇到了完全相同的问题。
在我的例子中,通过在 CMainFrame
中覆盖 PostNcDestroy
解决了这个问题。似乎在主框架窗口中处理最后一条消息可以使一切正常:
virtual void PostNcDestroy();
void CMainFrame::PostNcDestroy()
【讨论】:
【参考方案5】:另一种可能性是在关闭过程中发生断言失败。例如,在破坏窗户时。
我发现发生这种情况时,ExitInstance
也会被跳过。
因此,在关闭应用程序之前,请清除输出/调试日志窗口并查看是否打印了这样的消息。
如果是这种情况,请解决问题并查看是否再次调用ExitInstance
。
【讨论】:
以上是关于在 MFC 应用程序中未调用 ExitInstance的主要内容,如果未能解决你的问题,请参考以下文章
使用 Ninja 使用 CMake 构建的 Unicode MFC 应用程序中未解决的 WinMain 错误
在核心数据实用程序教程中未调用 setNilValueForKey