收到 wincore.cpp 中一个 " ASSERT " BUG: 当 MFC 应用程序 Visual C++ 中 MFC 规则 DLL 中调用函数声明
2007-07-02 14:50 flyingfish 阅读(6076) 评论(0) 编辑 收藏 举报今日将VC2005写的DLL的源码转到VC6时,弹出对话框时,报告:
---------------------------
Microsoft Visual C++ Debug Library
---------------------------
Debug Assertion Failed!
Program: D:\工作目录\Topology VC6.0\Bin\Test_Topology.exe
File: wincore.cpp
Line: 884
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
---------------------------
终止(A) 重试(R) 忽略(I)
---------------------------
经查,好像是VC6的Bug。
http://support.microsoft.com/kb/194300/zh-cn
收到 wincore.cpp 中一个 " ASSERT " BUG: 当 MFC 应用程序 Visual C++ 中 MFC 规则 DLL 中调用函数声明
我的总结:在调用Dll中资源时尽量用下边的语句代替AFX_MANAGE_STATE(AfxGetStaticModuleState());可以绕过这个错误。
//AFX_MANAGE_STATE(AfxGetStaticModuleState());
HMODULE hDLL=GetModuleHandle("SpatialReference.dll");
HINSTANCE hEXE=AfxGetResourceHandle();
AfxSetResourceHandle((HINSTANCE)hDLL);
//函数返回之前:
// AfxSetResourceHandle(hEXE);
微软网站的解决办法是:
症状
当 MFC EXE SDI / MDI 应用程序上下文中的命令处理程序调用 MFC 规则 DLL, 创建模式对话框, MFC 中导出函数以下断言可能触发:
ASSERT wincore.cpp 行 884 中
ASSERT wincore.cpp 行 883 中
如果忽略, 应用程序行为通常断言。 EXE 和规则 DLL 必须动态链接到 MFC。
原因
当父未显式指定模式对话框, MFC PreModal() 调用中确定与调用到 CWnd::GetSafeOwner_() 父。该调用返回路由框架 (AfxGetThreadState() "-> m_pRoutingFrame)。 m_pRoutingFrame 分配命令处理程序中。 [ 请参阅 CFrameWnd::OnCmdMsg() 中 CPushRoutingFrame ]
EXE, 到框架窗口是 EXE 中命令处理程序中设置路由框架。 因为线程状态是 EXE 和 DLL, 中相同 AfxGetThreadState() "-> m_pRoutingFrame 返回 EXE 框架窗口。 临时柄映射是 DLL, 为 CDialog::PreModal() 调用当调用 CWnd::FromHandle(::GetActiveWindow()) 中路由框架中创建临时 CWnd。 此断言, CWnd::AssertValid(), 中由事实路由框架临时 CWnd 的规则 DLL 临时柄映射中存在不匹配。
此问题影响的规则 DLL, 其中 CWnd::GetSafeOwner_() 称为上下文中命令处理程序中创建的所有模式窗口。 CWnd::GetSafeOwner_() 称为模式窗口的创建过程。 这包括 MFC 消息框、 OLE 属性页、 CDatabase::Connect、 对话框、 属性页和 OLE 忙对话框中。 请注意因为 CWnd::GetSafeOwner_() 是不调用在此上下文中, 此问题不影响无模式窗口不。
解决方案
一个解决办法是: 暂时在是 DoModal() 调用期间设置 AfxGetThreadState() "-> m_pRoutingFrame 到 NULL。 可以使用以下代码:
class tempRoutingFrame { CFrameWnd* m_pFrame ; public: tempRoutingFrame(CFrameWnd * pWnd= NULL) { // Save current value m_pFrame = AfxGetThreadState()->m_pRoutingFrame; // Set to value passed in. NULL by default. AfxGetThreadState()->m_pRoutingFrame = pWnd; } ~tempRoutingFrame() { // Restore m_pRoutingFrame to original value. AfxGetThreadState()->m_pRoutingFrame = m_pFrame; } }; extern "C" void __declspec(dllexport) TestFunction(); void TestFunction() { AFX_MANAGE_STATE(AfxGetStaticModuleState()) #ifdef _DEBUG // Workaround for ASSERT in WINCORE.CPP 884 (CWnd::AssertValid) tempRoutingFrame rframe; #endif CMyDialog dlg; dlg.DoModal(); }其他解决办法, 对对话框和属性表, 而言是要明确设置对话框中的父级如下:
void TestFunction() { AFX_MANAGE_STATE(AfxGetStaticModuleState()) CMyDialog dlg(AfxGetMainWnd()); dlg.DoModal(); }
状态
Microsoft 已确认这是了本文开头列出 Microsoft 产品中存在错误。
早在 Visual Studio 6.0 Service Pack 3 中得到解决此错误。 有关 VisualStudio, ServicePack 详细信息请单击下列文章编号, 查看 Microsoft 知识库文章中文章:
194022 (http://support.microsoft.com/kb/194022/) Visual Studio 6.0 服务包, 什么, 其中, 为什么
194295 (http://support.microsoft.com/kb/194295/) 如何判断安装 VisualStudio 服务包
更多信息
复现行为的步骤
1.使用应用程序向导创建常规 MFCDLL 项目。
2.确定和取消按钮和一个编辑控件, 创建新的对话框框资源。
3.创建对于从 CDialog 派生对话框类。 命名该类 CMyDialog。
4.mydialog.cpp 中添加下列函数:
extern "C" void __declspec(dllexport) TestFunction(); void TestFunction() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CMyDialog dlg; dlg.DoModal(); }
5.生成 DLL。
6.创建默认应用程序向导应用 EXE 项目。
7.使用以下替换 OnAppAbout 函数:
extern "C" void __declspec(dllimport) TestFunction(); void CMyTestApp::OnAppAbout() { TestFunction(); }
8.添加导出库向第 6 步中创建项目第 5 步中创建。
9.将步骤 5 到 Debug 文件夹为第 6 步中生成应用程序中生成 DLL。
10.生成并运行。
11.在 帮助 菜单上, 单击 关于 。
结果 : ASSERTS wincore.cpp, 中 883 和 884 行被触发。
参考
MFC 模块状态实现 TN058: