2011-06-27 1 views
6

Je coup d'oeil dans le code de mon ancêtre et a découvert une fuite dans la situation suivante:Un sommeil de fil provoque une fuite de mémoire

1) Application Lancer
b) Une fois l'application lancée, fermez le applicaiton dans les 4 secondes

le message de fuite:

f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\thrdcore.cpp(306) : {58509} client block at 0x016DFA30, subtype c0, 68 bytes long. 

par la suite, je suis passé par le code, trouvé sur le point de la cause suspecte à un 4secs de sommeil à contrôler la fonction de thread de travail.

Le programme d'essai:

UINT InitThread(LPVOID pParam) 
{ 
     Sleep(4000); //4000 is the default value, it reads from a registry key. 
     CMyMFCTestProjectDlg* pTest = (CMyMFCTestProjectDlg*)pParam; 
     pTest->DoSomething(); 
     return 0; //--> Exit thread 
} 

BOOL CMyMFCTestProjectDlg::OnInitDialog() { 
... 
AfxBeginThread(InitThread, this); 
... 
} 

Si je réduis/retirer de la minuterie de sommeil, la fuite sera résolu.
Cependant, j'aimerais savoir comment cela se passe. Soit en raison de thread de travail ou de terminaison de thread graphique? Est-ce que le thread de travail se ferme après que le thread de l'interface graphique provoque ce problème? Est-ce que quelqu'un peut remonter le moral de ma journée en m'aidant à expliquer cela? Je suis perdu ....

+0

Ce n'est pas le sommeil. Vous devez poster plus de code. Que fait le fil contenant le sommeil? – Matt

+0

@Matt H: Il y a d'autres codes dans le thread. C'est un "thread dormant" qui peut fournir une option pour retarder l'exécution du code restant. Laissez-moi essayer d'éditer le code ... – wengseng

Répondre

6

Il semble que le thread de travail n'ait pas la possibilité de se fermer correctement après la fermeture de l'application, car le processus se termine avant qu'il ne se termine. Le système d'exploitation est généralement assez bon pour nettoyer les ressources par lui-même, il ne peut donc pas être un problème. Cependant, il est probablement préférable d'attendre que ce thread soit fermé avant de permettre à l'application de s'arrêter. Bien que cela ressemble à cela, cela entraînera un délai de 4 secondes dans la fermeture de votre application. Si cela n'est pas acceptable, vous devrez ajouter un mécanisme au thread pour recevoir l'événement shutdown du thread principal des applications. Par exemple, si vous remplacez les threads de travail « sommeil », avec un WaitForSingleObject d'un événement:

DWORD res = WaitForSingleObject(
    shutdownEvent, 
    4000); // timeout 
if(res == WAIT_OBJECT_0) 
{ 
    // received the shutdownEvent, exit 
    return 0; 
} 
// The delay has elapsed, continue with rest of thread. 
. . . 

Ensuite, lorsque vous êtes en train de fermer dans votre thread principal, définissez l'événement, puis attendre que le thread pour quitter , il devrait quitter presque immédiatement:

SetEvent(this->shutdownEvent); 
WaitForSingleObject(pThread->m_hThread, INFINITE); // pThread is returned from AfxBeginThread 
+0

La fermeture d'une application implique généralement l'appel de ExitProcess(). Cette API arrête tous les threads en cours d'exécution sauf l'appelant, et arrête cela aussi après le détachement de la DLL. Il n'est pas impératif d'attendre explicitement que les autres threads de processus se terminent - le système d'exploitation ne les arrêtera pas, quel que soit l'état dans lequel ils se trouvent - bloqué, dormant ou s'exécutant sur un autre processeur, le système d'exploitation ne s'en soucie pas. De nombreux problèmes d'arrêt sont en fait * causés * en attendant explicitement la sortie des threads secondaires, empêchant ainsi le thread principal d'atteindre ExitProcess() et donc de fermer l'application. –

4

Vous devriez arrêter vos threads gracieusement avant que votre processus ne disparaisse. Vous pouvez demander au thread principal d'attendre que le ou les autres threads se terminent ou que le thread principal signale aux autres threads de quitter.

+0

'Vous devriez éteindre vos threads avec élégance avant que votre processus ne disparaisse'. Pourquoi? Le système d'exploitation est très bon pour arrêter les threads. Il y a beaucoup de cas de problèmes d'arrêt qui sont réellement provoqués par des tentatives pour signaler aux threads de quitter et attendre jusqu'à ce qu'ils l'aient fait. Si le thread n'est pas coopératif, (peut-être bloqué sur une API bloquante), le thread principal reste également bloqué et n'atteint pas le processus ExitProcess() qui aurait terminé tous les threads de toute façon. –

0

68 octets?

Si l'application s'arrête réellement, c.-à-d. a disparu du gestionnaire de tâches 'Applications' et 'Processus', et le seul effet de cette 'fuite' est d'émettre un message de débogage au début, il suffit d'éteindre le débogage et de l'oublier.

Il s'agit probablement d'une interruption de l'arrêt MFC, de certaines structures qui ne peuvent pas être libérées en toute sécurité lors de l'arrêt et qui restent à nettoyer pour le système d'exploitation. Avec les 99,9% d'applications qui ne sont pas continuellement redémarrées/arrêtées, une fuite de 68 octets à l'arrêt, même si elle n'a pas été nettoyée, n'influencerait pas le fonctionnement d'une machine Windows de manière notable entre le redémarrage intervalles imposés chaque 'Patch Tuesday'.

Je suis sûr que vous avez beaucoup plus de bugs avec des effets plus graves à traiter. Sinon, vous pouvez avoir quelques-uns des miens!

Mfg, Martin