2009-03-31 6 views
1

Après avoir basculé de VS2005 à VS2008 SP1, j'ai trouvé un problème que je ne peux pas expliquer.
Un programme fonctionne correctement sous VS2005 en mode release et debug. Sous VS2008, lorsque vous entrez dans le débogueur, un assert est levé.
Si je laisse le programme s'exécuter (en mode debug ou release), pas d'assertion du tout.Assertion dans VS2008 mais pas dans VS2005

J'ai passé presque deux jours sur ceci et je ne comprends pas ce que je fais mal.

Description du programme: J'ai un programme de dialogue MFC qui crée une qui crée la boîte de dialogue principale de l'application thread utilisateur (CWinThread).
Un thread de travail boucle indéfiniment et publie chaque seconde un message dans le dialogue. Le message est traité dans le thread graphique.

Certaines parties de mon code:

Le InitInstance du fil de IUG:

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

Le thread de travail:

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

    return 0; 
} 

Le gestionnaire de messages dialogue est comme ceci:

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

Cela fonctionne parfaitement bien avec VS2005. Mais avec VS2008, mais dès qu'un a mis un point d'arrêt et entrer dans le mode de débogage, j'ai une assertion soulevée ???
ligne 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. 

Si je retire le fil de l'interface graphique et de créer la boîte de dialogue dans le fil CWinApp, le problème ne se produit plus.

Est-ce que quelqu'un a une idée?
Est-ce que je fais quelque chose de mal?

Merci

Répondre

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

Oui, je sais. Je ne manipule pas les fenêtres dans un autre fil, je ne fais que poster un message dessus. J'ai essayé d'utiliser le HWND brut mais le problème est toujours là. Quoi qu'il en soit, cela n'explique pas pourquoi cela fonctionne bien avec VS2005 et pas avec VS2008. –

+0

wincore.cpp est différent pour VC++ versions 8 et 9. La version 8 est VS 2005 et la version 9 est VS 2008 –

+0

Je recommanderais de passer le HWND de la boîte de dialogue principale comme paramètre de thread, puis dans l'appel de thread CWnd: : FromHandle (hWnd) -> PostMessage (...); – Ismael

0

@Ismael: Je l'avais déjà essayé assert est encore tiré. Le seul moyen que j'ai trouvé pour supprimer l'affirmation est de créer la boîte de dialogue dans le thread CWinApp. Mais cela n'explique pas ce qui se passe car il y a toujours le thread de travail qui publie dans le dialogue toutes les secondes. En tout cas, merci.

@ daanish.rumani: J'ai vérifié le wincore.cpp et le CWnd :: AssertValid() est exactement le même (mais il y a beaucoup de différences dans le reste des fichiers).

J'accepterais qu'un morceau de code fonctionne avec VS2005 et non VS2008, mais

  1. je ne vois pas ce que je fais mal. Si je fais quelque chose de mal, quelle est la bonne façon de procéder?
  2. Pourquoi l'affirmation n'est déclenchée que lorsqu'un point d'arrêt est atteint et que je passe l'appel en veille? Je peux exécuter le programme très bien, même quand il est compilé en mode débogage, tant que je n'entrerai pas dans le débogueur. Pourrait-il être un bogue dans le débogueur?
+0

Idéalement, vous devriez éditer votre question originale pour ajouter ces précisions. Les réponses sont pour les autres :) –

+0

Oui. A moins que vous ne trouviez vraiment un _answer_, ne postez pas de réponse. Il suffit d'éditer votre question et/ou de commenter en dessous des réponses ou des commentaires d'autres personnes. –

+0

Désolé pour ça, je ferai attention –

Questions connexes