Non sono sicuro che tu sia ancora interessato a questo, ma attualmente sto eseguendo il debug di una situazione simile. Discussioni che utilizzano pthread_exit
fare in modo che valgrind segnali i blocchi raggiungibili. Il motivo sembra essere spiegato abbastanza bene qui:
https://bugzilla.redhat.com/show_bug.cgi?id=483821
Essenzialmente sembra pthread_exit
provoca un dlopen
che non viene mai ripulito esplicitamente quando il processo termina.
Il seguente test case minimo mostra il comportamento che descrivi:
#include <pthread.h>
#include <unistd.h>
void *app1(void *x)
{
sleep(1);
pthread_exit(0);
}
int main()
{
pthread_t t1;
pthread_create(&t1, NULL, app1, NULL);
pthread_join(t1, NULL);
return 0;
}
valgrind --leak-check=full --show-reachable=yes
mostra 5 blocchi allocati da funzioni chiamate da pthread_exit()
che non è liberato ma ancora raggiungibile all'uscita dal processo. Se pthread_exit(0);
è sostituito da return 0;
, i 5 blocchi non sono allocati.
Tuttavia, se provi a creare e unire un gran numero di thread, scoprirai che la quantità di memoria non liberata in uso all'uscita non aumento. Questo, e il fatto che sia ancora raggiungibile, indica che stai solo vedendo una stranezza dell'implementazione di glibc. Diverse funzioni glibc allocano memoria con malloc()
la prima volta che vengono chiamati, che mantengono allocati per il resto della durata del processo. glibc non si preoccupa di liberare questa memoria all'uscita del processo, poiché sa che il processo verrà comunque interrotto:sarebbe solo uno spreco di cicli della CPU.
Stai effettivamente usando C ++, per caso? Per chiarire, il tuo file sorgente termina con un .c
e lo stai compilando con gcc
, non g++
?
Sembra ragionevolmente probabile che la tua funzione stia allocando risorse che prevedi vengano ripulite automaticamente quando la funzione ritorna. Oggetti C++ locali come std::vector
o std::string
fallo, e i loro distruttori probabilmente non verranno eseguiti se chiami pthread_exit
, ma verrebbe ripulito se tornassi.
La mia preferenza è evitare API di basso livello come pthread_exit
, e ritorna sempre dalla funzione thread, ove possibile. Sono equivalenti, tranne che pthread_exit
è un costrutto de facto di controllo del flusso che aggira il linguaggio che stai usando, ma return
non.