1

VS2005 から VS2008 SP1 に切り替えた後、説明できない問題が見つかりました。
プログラムは、リリース モードとデバッグ モードの両方で VS2005 の下で正常に動作します。VS2008 では、デバッガーに入るとアサートが発生します。
プログラムを (デバッグ モードまたはリリース モードで) 実行すると、アサーションはまったく発生しません。

私はこれにほぼ2日を費やしましたが、何が間違っているのかわかりません。

プログラムの説明: アプリケーションのメイン ダイアログを作成するユーザー スレッド (CWinThread) を作成する MFC ダイアログ ベースのプログラムがあります。
ワーカー スレッドは無限にループし、毎秒メッセージをダイアログに投稿します。メッセージは 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 スレッドに作成すると、問題は発生しなくなります。

誰にもアイデアはありますか?
私は何か間違ったことをしていますか?

ありがとうございました

4

2 に答える 2

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.
于 2009-03-31T15:15:25.133 に答える
0

@Ismael:アサートがまだ起動されていることをすでに試しました。アサートを削除する唯一の方法は、ダイアログを CWinApp スレッドに作成することです。しかし、毎秒ダイアログに投稿するワーカー スレッドがまだあるため、これは何が起こるかを説明していません。とりあえずありがとう。

@daanish.rumani: wincore.cpp を確認しましたが、CWnd::AssertValid() はまったく同じです (ただし、残りのファイルには多くの違いがあります)。

コードの一部が VS2008 ではなく VS2005 で動作することは認めますが、

  1. 何が間違っているのかわかりません。何か間違ったことをした場合、どのように進めるのが正しいですか?
  2. ブレークポイントにヒットし、Sleep 呼び出しをステップ オーバーしたときにのみアサートが発生するのはなぜですか? デバッガーに入らない限り、デバッグモードでコンパイルされた場合でも、プログラムを正常に実行できます。デバッガのバグでしょうか?
于 2009-04-01T08:34:12.967 に答える