2009-03-31 8 views
1

Nach dem Wechsel von VS2005 zu VS2008 SP1 habe ich ein Problem gefunden, das ich nicht erklären kann.
Ein Programm funktioniert unter VS2005 im Freigabe- und Debug-Modus. Unter VS2008 wird beim Eingeben des Debuggers eine Assertion ausgelöst.
Wenn ich das Programm laufen lassen (im Debug-oder Release-Modus), keine Behauptung überhaupt.Behauptung in VS2008, aber nicht in VS2005

Ich verbrachte fast zwei Tage damit und ich verstehe nicht, was ich falsch mache.

Beschreibung des Programms: Ich habe einen Dialog MFC basiertes Programm, das einen Benutzer-Thread (CWinThread) erzeugt, die den Hauptdialog der Anwendung erzeugt.
Ein Worker-Thread wird endlos wiederholt und sendet jede Sekunde eine Nachricht an das Dialogfeld. Die Nachricht wird im GUI-Thread verarbeitet.

Einige Teile meines Code:

Die InitInstance des GUI-Thread:

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

Der Arbeiter-Thread:

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

    return 0; 
} 

Der Dialog Nachrichtenhandler ist wie folgt:

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

Dies funktioniert perfekt mit VS2005. Aber mit VS2008, aber sobald ein Breakpoint gesetzt und den Debugging-Modus betreten, habe ich eine Assertion ausgelöst ???
wincore.cpp Linie 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. 

Wenn ich die GUI-Thread, und erstellen Sie den Dialog in den CWinApp Thread zu entfernen, tritt das Problem nicht mehr nicht.

Hat jemand eine Idee?
Mache ich etwas falsch?

Danke

Antwort

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

Ja, ich weiß. Ich manipuliere die Fenster in einem anderen Thread nicht, sondern schreibe einfach eine Nachricht dorthin. Ich habe versucht, die rohe HWND zu verwenden, aber das Problem ist immer noch da. Wie auch immer, es erklärt nicht, warum es gut mit VS2005 und nicht mit VS2008 funktioniert. –

+0

wincore.cpp ist für VC++ Version 8 und 9 unterschiedlich. Version 8 ist VS 2005 und Version 9 ist VS 2008 –

+0

Ich würde empfehlen, die HWND aus dem Hauptdialog als Thread-Parameter und dann im Thread-Aufruf CWnd übergeben: : FromHandle (hWnd) -> PostMessage (...); – Ismael

0

@Ismael: Ich hatte bereits versucht, dass die Assertion noch gebrannt wird. Die einzige Möglichkeit, die Assertion zu entfernen, besteht darin, den Dialog im CWinApp-Thread zu erstellen. Aber das erklärt nicht, was passiert, da immer noch der Worker-Thread jede Sekunde im Dialog posten wird. Wie auch immer, danke.

@ daanish.rumani: Ich habe die wincore.cpp überprüft und die CWnd :: AssertValid() ist genau das gleiche (aber es gibt viele Unterschiede in den Rest der Dateien).

Ich würde annehmen, dass ein Stück Code mit VS2005 funktioniert und nicht VS2008, aber

  1. kann ich nicht sehen, was ich falsch machen. Wenn ich etwas falsch mache, was ist der richtige Weg?
  2. Warum wird die Assert nur ausgelöst, wenn ein Haltepunkt erreicht wird und ich den Sleep-Anruf überspringe? Ich kann das Programm fein ausführen, auch wenn es im Debug-Modus kompiliert wird, solange ich den Debugger nicht betreten. Könnte es ein Fehler im Debugger sein?
+0

Im Idealfall sollten Sie Ihre ursprüngliche Frage bearbeiten, um diese Präzisionen hinzuzufügen. Antworten sind für andere :) –

+0

Ja. Sofern Sie nicht selbst eine Antwort gefunden haben, schreiben Sie keine Antwort. Bearbeiten Sie einfach Ihre Frage und/oder kommentieren Sie die Antworten oder Kommentare anderer Personen. –

+0

Entschuldigung dafür, ich werde aufpassen –