在VS2008中断言但在VS2005中没有断言

时间:2009-03-31 14:56:28

标签: c++ visual-studio mfc assertions

从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线程中创建对话框,则不再出现此问题。

有人有任何想法吗?
我做错了吗?

谢谢

2 个答案:

答案 0 :(得分:4)

// 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.

答案 1 :(得分:0)

@Ismael:我已经尝试过断言仍然被解雇了。我发现删除断言的唯一方法是在CWinApp线程中创建对话框。 但这并没有解释会发生什么,因为仍然有工作线程每秒都会发布到对话框中。 无论如何,谢谢。

@ daanish.rumani:我检查了wincore.cpp,CWnd :: AssertValid()完全相同(但其余文件有很多不同之处)。

我会接受一段代码适用于VS2005而不是VS2008,但是

  1. 我看不出自己做错了什么。 如果我做错了什么,正确的方法是什么?
  2. 为什么只有在遇到断点并且我跳过Sleep呼叫时才会触发断言? 只要我不进入调试器,即使在调试模式下编译,我也可以正常运行程序。 它可能是调试器中的错误吗?