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

发布于 2024-07-16 07:32:17 字数 2151 浏览 6 评论 0原文

从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 线程中,则问题不会再出现。

有人有什么想法吗?
难道我做错了什么?

谢谢

After switching from VS2005 to VS2008 SP1, I found an issue that I can't explain.
A program works fine under VS2005 in both release and debug mode. Under VS2008, when entering the debugger an assert is raised.
If I let the program run (in debug or release mode), no assertion at all.

I spent almost two days on this and I don't understand what I do wrong.

Description of the program:
I have a MFC dialog based program that creates a user thread (CWinThread) that creates the main dialog of the application.
A worker thread loops infinitely and posts each second a message to the dialog. The message is processed in the gui thread.

Some parts of my code:

The InitInstance of the gui thread:

BOOL CGraphicalThread::InitInstance()
{
    CGUIThreadDlg* pDlg = new CGUIThreadDlg();
    pDlg->Create(CGUIThreadDlg::IDD);
    m_pMainWnd = pDlg;
    AfxGetApp()->m_pMainWnd = pDlg;
    return TRUE;
}

The worker thread:

UINT ThreadProc(LPVOID pVoid)
{
    do
    {
        AfxGetApp()->m_pMainWnd->PostMessage(WM_APP+1, (WPARAM)new CString("Hello"), NULL);
        Sleep(1000);
    }
    while(!bStopThread);

    return 0;
}

The dialog message handler is like this:

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;
}

This works perfectly fine with VS2005.
But with VS2008, but as soon as a put a breakpoint and enter the debugging mode, I have an assertion raised ???
wincore.cpp line 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.

If I remove the GUI thread and create the dialog into the CWinApp thread, the problem doesn't occur anymore.

Does anybody have any idea?
Am I doing something wrong?

Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

厌味 2024-07-23 07:32:17
// 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.
// 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.
放赐 2024-07-23 07:32:17

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

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

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

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

@Ismael: I had already tried that the assert is still fired. The only way I found to remove the assert is to create the dialog into the CWinApp thread.
But this doesn't explain what happens since there's still the worker thread that post to the dialog every second.
Anyway , thanks.

@daanish.rumani: I've checked the wincore.cpp and the CWnd::AssertValid() is exactly the same (but there's of lot of differences in the rest of the files).

I would accept that a piece of code works with VS2005 and not VS2008, but

  1. I can't see what I do wrong.
    If I do something wrong, what is the correct way to proceed?
  2. Why the assert is only fired when a breakpoint is hit and I step over the Sleep call?
    I can run the program fine, even when its compiled in debug mode, as long as I don't enter the debugger.
    Could it be a bug in the debugger?
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文