2009-03-31 6 views
1

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

私はこれに約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
// 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. 
+0

はいわかっています。私は別のスレッドでウィンドウを操作しているわけではなく、単にメッセージをポストしています。 生のHWNDを使用しようとしましたが、問題はまだ残ります。 とにかく、VS2005では正常に動作し、VS2008では正常に動作しない理由については説明しません。 –

+0

wincore.cppはVC++バージョン8と9で異なります。バージョン8はVS 2005でバージョン9はVS 2008 –

+0

メインダイアログからHWNDをスレッドパラメータとして渡し、スレッドコールCWndに渡すことをお勧めします。 :FromHandle(hWnd) - > PostMessage(...); – Ismael

0

@Ismaelありがとう:私はすでにアサートがまだ発射されていることをしようとしました。アサートを削除するために私が見つけた唯一の方法は、ダイアログをCWinAppスレッドに作成することです。 しかし、毎秒ダイアログにポストするワーカースレッドがまだ存在するので、これは何が起こるか説明しません。とにかく、ありがとうございます。

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

私は私が間違って何をすべきかを見ることができないコードの一部が、VS2005とVS2008でないと動作することを受け入れますが、

  1. でしょう。 私が何か間違っている場合は、進める正しい方法は何ですか?
  2. なぜアサートはブレークポイントがヒットしたときにのみ起動され、スリープコールをステップオーバーしますか? 私はデバッガに入っていない限り、コンパイルされたデバッグモードであっても、プログラムを正常に実行できます。 デバッガのバグでしょうか?
+0

これらの精度を追加するには、元の質問を編集するのが理想的です。回答は他の人のためです:) –

+0

はい。本当にあなた自身が_answer_を見つけていない限り、回答を投稿しないでください。あなたの質問を編集したり、他の人の回答やコメントの下にコメントしてください。 –

+0

申し訳ありません、私は世話をします –

関連する問題