Il existe une fuite de mémoire connue lorsque vous terminez un processus avec l’exécution de pthreads non détachés. Cependant, le détachement du thread ne semble pas être une solution. Prenons l’exemple minimal suivant:
#include #include static void* thread(void* _) { for(;;); return NULL; } int main(void) { pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_t tid; pthread_create(&tid, &attr, thread, NULL); pthread_attr_destroy(&attr); return 0; }
Un thread détaché avec une boucle infinie est créé et le processus est immédiatement terminé. Selon pthread_detach(3)
, les ressources du thread doivent être automatiquement relâchées sur le système une fois le processus terminé. Ce n’est cependant pas ce qui se passe:
gcc -pthread cc valgrind --leak-check=full a.out ==9341== Command: a.out ==9341== ==9341== ==9341== HEAP SUMMARY: ==9341== in use at exit: 272 bytes in 1 blocks ==9341== total heap usage: 1 allocs, 0 frees, 272 bytes allocated ==9341== ==9341== 272 bytes in 1 blocks are possibly lost in loss record 1 of 1 ==9341== at 0x4C2ABB4: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==9341== by 0x4012598: _dl_allocate_tls (dl-tls.c:296) ==9341== by 0x4E3C7B5: pthread_create@@GLIBC_2.2.5 (allocatestack.c:579) ==9341== by 0x400825: main (in /home/witiko/a.out) ==9341== ==9341== LEAK SUMMARY: ==9341== definitely lost: 0 bytes in 0 blocks ==9341== indirectly lost: 0 bytes in 0 blocks ==9341== possibly lost: 272 bytes in 1 blocks ==9341== still reachable: 0 bytes in 0 blocks ==9341== suppressed: 0 bytes in 0 blocks
Devrais-je m’inquiéter? Dans le programme actuel, j’ai plusieurs threads bloquants, donc, comme dans l’exemple minimal, je ne peux pas vraiment pthread_join()
avec eux. Dois-je appeler pthread_cancel()
au lieu de exit()
directement?
Revenir de main
est équivalent à une exit
de l’ensemble du processus, donc c’est une manière assez grossière de terminer votre thread détaché. Votre thread ne s’est tout simplement pas arrêté lorsque la fonction main
se termine, il ne le fait plus tard que lorsque le mécanisme de exit
force. Donc, valgrind manque la libération des ressources du thread.
Le fait que valgrind vous dise qu’il y a une fuite de mémoire ne devrait pas vous inquiéter vous-même, mais le fait que votre thread soit terminé sans pouvoir nettoyer et / ou terminer sa tâche devrait vous inquiéter.
Si vous voulez que votre thread continue son exécution après la fin de votre thread main
, vous devez terminer par main par pthread_exit
au lieu de return
. Ensuite, c’est à votre fil détaché de décider quand se terminer. Il pourrait en être ainsi, en recevant les informations nécessaires à travers une variable d’état qui est définie de manière atomique ou via un mécanisme de mutex / condition.