2010-11-30 36 views
0

Mon application plante quand elle quitte la fonction de thread. Voici comment mon fils est initialisé:L'application tombe en panne sur la sortie de thread - C++

LPTHREAD_START_ROUTINE pThreadStart = (LPTHREAD_START_ROUTINE)NotifyWindowThreadFn; 
void * pvThreadData = reinterpret_cast<void *>(_pobjSerialPort); 

// Create the exit notify window thread event handle. 
_hNotifyWindowThreadExitEvent = ::CreateEvent(
    NULL,       // No security 
    TRUE,       // Create a manual-reset event object 
    FALSE,       // Initial state is non-signaled 
    NULL       // No name specified 
    ); 

if (_hNotifyWindowThreadExitEvent == NULL) 
{ 
    TRACE(_T("CreateNotifyWindow : Failed to get a handle for the exit message-only window event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__); 
    return ::GetLastError(); 
} 

// Create the notify window thread to begin execution on its own. 
_hNotifyWindowThread = ::CreateThread(
    NULL,       // No security attributes. 
    0,        // Use default initial stack size. 
    pThreadStart,     // Function to execute in new thread. 
    pvThreadData,     // Thread parameters. 
    0,        // Use default creation settings. 
    NULL       // Thread ID is not needed. 
    ); 

if (_hNotifyWindowThread == NULL) 
{ 
    TRACE(_T("CreateNotifyWindow : Failed to create handle for message-only window thread.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__); 
    return ::GetLastError(); 
} 

Ceci est la partie de ma fonction de fil qui est exécuté:

DWORD NotifyWindowThreadFn(void * pParam) 
{ 
    static CNotifyWindow * pobjNotifyWindow = NULL; 
    CSerialPort * pobjSerialPort = reinterpret_cast<CSerialPort *>(pParam); 

    // Create notify window to handle surprize removal/insertion events... 
    try 
    { 
     pobjNotifyWindow = new CNotifyWindow(); 
    } 
    catch (DWORD error) 
    { 
     return error;    // 1. PC gets here 
    } 
    catch (long error) 
    { 
     return error; 
    } 
    catch (...) 
    { 
     return ERROR_CANNOT_MAKE; 
    } 

    /* Other stuff that is not executed due to return. */ 

}          // 2. PC then gets here 

Lorsque l'application se bloque, Visual Studio me donne ce message d'erreur:

Windows a déclenché un point d'arrêt dans CppTestConsole.exe.

Cela peut être dû à une corruption du tas, qui indique un bogue dans CppTestConsole.exe ou l'une des DLL qu'il a chargé.

Cela peut également être dû au fait que l'utilisateur a appuyé sur F12 alors que CppTestConsole.exe a le focus.

La fenêtre de sortie peut contenir plus d'informations de diagnostic.

La fenêtre de sortie n'a rien de particulièrement utile. Seulement ...

Le thread 'NotifyWindowThreadFn' (0x414) s'est terminé avec le code 0 (0x0).

Ensuite, il montre qu'un tas de DLL est déchargé. Lorsque je clique sur le bouton Break, le PC se trouve à la fin de _CrtIsValidHeapPointer dans dbgheap.c. Est-ce que quelqu'un a des idées sur la raison pour laquelle mon application plante quand le thread se termine? Ne devrais-je pas revenir directement d'une fonction filetée? Merci.

Répondre

3

Je peux me tromper, mais il semble que vous essayez de créer une fenêtre à partir d'un thread de travail. Ne fais pas ça. Windows a besoin de la pompe de message pour fonctionner, et il n'y a qu'une pompe de message dans votre application - c'est dans le fil principal.

+0

Est-ce que la fonction 'WndProc' exécuter encore quand il reçoit des messages? Je pensais que 'CreateWindow' ne démarre pas la fenêtre dans un nouveau thread; il s'exécute dans le thread qui l'a créé. –

+0

Je me suis moqué de moi-même pour avoir dit "fais-moi confiance". Si quelqu'un me disait ça, je serais comme "Ouais, c'est vrai". Quoi qu'il en soit, expliquez pourquoi vous pensez que vous voulez que votre fenêtre s'exécute dans un thread de travail, et nous pouvons en discuter. –

+0

Fondamentalement, la fenêtre est créée uniquement pour gérer les événements surprise de suppression et d'insertion USB.Il n'a pas d'interface utilisateur. Lorsque ces événements sont déclenchés, 'WndProc' doit fonctionner de manière asynchrone pour marquer l'état du périphérique USB au reste de l'application dès que possible, afin que les E/S série avec le port USB puissent être suspendues ou reprises si nécessaire avec un impact minimal (c'est-à-dire des données perdues) à l'application que possible. –

0

Essayez d'utiliser _beginthreadex au lieu de CreateThread:

Un fil dans un fichier exécutable qui appelle la bibliothèque d'exécution C (CRT) devrait utiliser le _beginthreadex et fonctions _endthreadex pour la gestion des threads plutôt que CreateThread et ExitThread; cela nécessite l'utilisation de la version multithread du CRT . Si un thread créé à l'aide CreateThread appelle le CRT, le CRT peut terminer le processus dans des conditions de mémoire insuffisante.

+0

@Jim Fell ne semble pas faire quelque chose qui évoquerait ce problème. De plus, la plupart (pas tous) des problèmes qui résultent de l'utilisation de CreateThread() dans un thread utilisant le CRT ont été corrigés depuis longtemps. Ce n'est probablement pas le problème. –

+0

Probablement juste, bien que la création d'un nouvel objet ne devrait pas non plus détruire le tas/pile (même s'il s'agit d'une fenêtre). Je pense qu'Edwin a repéré le problème, cependant. (Ou au moins * un * problème. Pourrait être plusieurs. :)) –

1

vous devez déclarer et définir vous fonctionnez comme: DWORD WINAPI NotifyWindowThreadFn (void * pParam)

+0

+1 à cela. En fait, vous ne devriez pas avoir besoin de lancer votre pointeur de fonction. Que vous devez indiquer quelque chose ne va pas. –

+0

et supprimer cette coulée horrible, inutile et dangereux –

+0

@ Leo Davidson: bien pas entièrement. Si programme en C pour COM, vous ne pouvez pas les faire (je pensais). –