VS2008 中的断言,但 VS2005 中没有
Posted
技术标签:
【中文标题】VS2008 中的断言,但 VS2005 中没有【英文标题】:Assertion in VS2008 but not in VS2005 【发布时间】:2009-03-31 14:56:28 【问题描述】:从 VS2005 切换到 VS2008 SP1 后,我发现了一个我无法解释的问题。 一个程序在 VS2005 下在发布和调试模式下都能正常工作。在 VS2008 下,当进入调试器时,会引发一个断言。 如果我让程序运行(在调试或发布模式下),则根本没有断言。
我花了将近两天的时间,我不明白我做错了什么。
程序说明: 我有一个基于 MFC 对话框的程序,它创建一个用户线程 (CWinThread),该线程创建应用程序的主对话框。 工作线程无限循环并每秒向对话框发布一条消息。消息在 gui 线程中处理。
我的部分代码:
gui线程的InitInstance:
BOOL CGraphicalThread::InitInstance()
CGUIThreadDlg* pDlg = new CGUIThreadDlg();
pDlg->Create(CGUIThreadDlg::IDD);
m_pMainWnd = pDlg;
AfxGetApp()->m_pMainWnd = pDlg;
return TRUE;
工作线程:
UINT ThreadProc(LPVOID pVoid)
do
AfxGetApp()->m_pMainWnd->PostMessage(WM_APP+1, (WPARAM)new CString("Hello"), NULL);
Sleep(1000);
while(!bStopThread);
return 0;
对话消息处理程序是这样的:
LRESULT CGUIThreadDlg::OnMsg(WPARAM wp, LPARAM lp)
CListBox* pList = (CListBox*)GetDlgItem(IDC_LIST1);
CString* ps = (CString*)wp;
pList->InsertString(-1, *ps);
delete ps;
return 1L;
这与 VS2005 完美配合。 但是用VS2008,但是一旦下断点并进入调试模式,我就会提出一个断言??? wincore.cpp 第 906 行
CObject* p=NULL;
if(pMap)
ASSERT( (p = pMap->LookupPermanent(m_hWnd)) != NULL ||
(p = pMap->LookupTemporary(m_hWnd)) != NULL);
ASSERT((CWnd*)p == this); // must be us
// Note: if either of the above asserts fire and you are
// writing a multithreaded application, it is likely that
// you have passed a C++ object from one thread to another
// and have used that object in a way that was not intended.
// (only simple inline wrapper functions should be used)
//
// In general, CWnd objects should be passed by HWND from
// one thread to another. The receiving thread can wrap
// the HWND with a CWnd object by using CWnd::FromHandle.
//
// It is dangerous to pass C++ objects from one thread to
// another, unless the objects are designed to be used in
// such a manner.
如果我删除 GUI 线程并在 CWinApp 线程中创建对话框,问题就不会再出现了。
有人知道吗? 我做错了吗?
谢谢
【问题讨论】:
【参考方案1】:// Note: if either of the above asserts fire and you are
// writing a multithreaded application, it is likely that
// you have passed a C++ object from one thread to another
// and have used that object in a way that was not intended.
// (only simple inline wrapper functions should be used)
//
// In general, CWnd objects should be passed by HWND from
// one thread to another. The receiving thread can wrap
// the HWND with a CWnd object by using CWnd::FromHandle.
//
// It is dangerous to pass C++ objects from one thread to
// another, unless the objects are designed to be used in
// such a manner.
【讨论】:
是的,我知道。我不是在另一个线程中操作窗口,只是向它发布消息。我尝试使用原始 HWND,但问题仍然存在。无论如何,它并没有解释为什么它在 VS2005 上运行良好,而在 VS2008 上运行良好。 wincore.cpp 对于 VC++ 版本 8 和 9 是不同的。版本 8 是 VS 2005,版本 9 是 VS 2008 我建议将主对话框中的 HWND 作为线程参数传递,然后在线程中调用 CWnd::FromHandle(hWnd)->PostMessage(...);【参考方案2】:@Ismael:我已经尝试过断言仍然被触发。我发现删除断言的唯一方法是在 CWinApp 线程中创建对话框。 但这并不能解释会发生什么,因为仍然有工作线程每秒发布到对话框。 无论如何,谢谢。
@daanish.rumani:我检查了 wincore.cpp 和 CWnd::AssertValid() 完全相同(但其余文件有很多差异)。
我会接受一段代码适用于 VS2005 而不是 VS2008,但是
-
我看不出我做错了什么。
如果我做错了什么,正确的处理方法是什么?
为什么只有在遇到断点并且我跳过 Sleep 调用时才会触发断言?
我可以很好地运行程序,即使它在调试模式下编译,只要我不进入调试器。
会不会是调试器中的错误?
【讨论】:
理想情况下,您应该编辑原始问题以添加这些精度。答案是给别人的:) 是的。除非您真的自己找到了答案,否则不要发布答案。只需在其他人的答案或 cmets 下方编辑您的问题和/或评论即可。 对不起,我会注意的以上是关于VS2008 中的断言,但 VS2005 中没有的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server 2008 VS 2005 Reporting Services 整合SharePoint 2007 支持比较Part1