2013-07-14 3 views
15

Chaque fois que je crée un pthread, valgrind émet une fuite de mémoire,pourquoi pthread provoque une fuite de mémoire

Par exemple le code ci-dessous:

#include <stdio.h> 
#include <unistd.h> 
#include <pthread.h> 

void *timer1_function (void *eit){ 
    (void) eit; 
    printf("hello world\n"); 
    pthread_exit(NULL); 
} 

int main(void){ 
    pthread_t timer1; 
    pthread_create(&timer1, NULL, timer1_function, NULL); ///////line13 
    int i=0; 
    for(i=0;i<2;i++){usleep(1);} 
    return 0; 
} 

sorties valgrind

==1395== HEAP SUMMARY: 
==1395==  in use at exit: 136 bytes in 1 blocks 
==1395== total heap usage: 6 allocs, 5 frees, 1,134 bytes allocated 
==1395== 
==1395== 136 bytes in 1 blocks are possibly lost in loss record 1 of 1 
==1395== at 0x402A629: calloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==1395== by 0x4011304: allocate_dtv (dl-tls.c:297) 
==1395== by 0x4011AAB: _dl_allocate_tls (dl-tls.c:461) 
==1395== by 0x4052470: [email protected]@GLIBC_2.1 (allocatestack.c:571) 
==1395== by 0x8048566: main (test.c:13) 
==1395== 
==1395== LEAK SUMMARY: 
==1395== definitely lost: 0 bytes in 0 blocks 
==1395== indirectly lost: 0 bytes in 0 blocks 
==1395==  possibly lost: 136 bytes in 1 blocks 
==1395== still reachable: 0 bytes in 0 blocks 
==1395==   suppressed: 0 bytes in 0 blocks 

pourquoi pthread_create cause de un problème bien que j'utilise la page man comme référence, et comment puis-je le réparer?

+0

duplication possible de [erreurs de fuite de mémoire valgrind lors de l'utilisation de pthread \ _create] (http: // stackoverflow.com/questions/5610677/valgrind-memory-leak-errors-when-using-pthread-create) – nos

Répondre

22

Un thread est une ressource allouée et vous n'a pas libéré avant de quitter. Vous devriez appeler pthread_join; cela éliminerait également le besoin de votre boucle de sommeil hackish et incorrect. Il est possible que même une fois que vous corrigez cela, valgrind verra toujours une "fuite", car certaines implémentations de threads POSIX (je suppose que vous utilisez glibc/NPTL) mettent en cache et réutilisent les ressources de threads plutôt que de les libérer pleinement. Je ne suis pas sûr si valgrind fonctionne autour de ceci ou pas.

+1

+1. Je pense que votre deuxième paragraphe explique pourquoi j'ai vu l'approche suppressions dans ma réponse utilisée si souvent. – simonc

+0

Alternative à pthread_join: utilisez pthread_detach mais la fuite de mémoire reste. – Aubin

4

Je pense que valgrind analyse l'état de votre programme au moment où il se termine, ce qui est probable avant que le thread termine son exécution: deux microsecondes peuvent ne pas suffire pour écrire "Hello, world!\n" à la console. Ajout d'un appel à pthread_join devrait corriger cette fuite:

pthread_join(timer1, NULL); 
+3

Vous pouvez simplement passer un pointeur NULL pour le second argument plutôt qu'un pointeur vers une variable fictive. –

+0

@R .. Oui, je suppose que vous avez raison ... OP passe 'NULL' à 'pthread_exit', donc' pthread_join' pourrait aussi ignorer explicitement le résultat. Merci! – dasblinkenlight

0

La fuite de mémoire résulte du fait que si le thread est exécuté sans annulation, la mémoire allouée dynamiquement correspondante n'est pas libérée. Utilisez pthread_cancel() avec pthread_cleanup_push (CleanupHandler, NULL) et pthread_cleanup_pop (0) pour effectuer le nettoyage du thread après l'annulation.

1

J'ai vu des résultats similaires lorsque je ne parviens pas à appeler pthread_join. Lorsque j'appelle pthread_join, Valgrind n'indique aucune erreur de mémoire ou de fuite.

J'ai eu un résultat propre en utilisant pthread_kill pour voir si le thread existe toujours, puis en appelant join pour nettoyer et libérer des ressources.

int 
stop_worker(worker_t *self) 
{ 
    if (self) { 
     // signal the thread to quit 
      // (here using a variable and semaphore) 
     self->thread_quit=TRUE; 
     sem_post(&self->sem); 

     // wait for it to stop 
     // (could use counter, etc. to limit wait) 
     int test=0; 
     while (pthread_kill(self->thread,0) == 0) { 
      MDEBUG(MD_XF_LOGGER,"waiting for thread to exit...\n",test); 
      delay_msec(50); 
     } 

     // even though thread is finished, need to call join 
     // otherwise, it will not release its memory (and valgrind indicates a leak) 
     test=pthread_join(self->thread,NULL); 
     return 0;   
    } 
    return -1; 
} 
0

La fuite qui apparaît est liée à la DTV structure (vecteur dynamique de fil) qui est allouée dans le stockage local (tls) du thread enfant.

L'utilisation de pthread_join() dans le fil principal (c'est-à-dire le fil qui a engendré l'enfant) assurera la réparation de la fuite. Pour les cas d'utilisation où l'appel pthread_join() n'est pas requis, l'appel pthread_detach avec l'enfant pthread_t assure la libération de la mémoire.

De l'homme pour pthread_detach:

La fonction pthread_detach() marque le fil identifié par fil comme détaché. Lorsqu'un thread détaché se termine, ses ressources sont automatiquement libérées dans le système sans avoir besoin de un autre thread à joindre avec le thread terminé.

Questions connexes