No estoy seguro de si todavía está interesado en esto, pero actualmente estoy depurando una situación similar. Temas que usan pthread_exit
hacer que valgrind informe de bloques alcanzables. La razón parece estar bastante bien explicada aquí:
https://bugzilla.redhat.com/show_bug.cgi?id=483821
Esencialmente parece pthread_exit
provoca un dlopen
que nunca se limpia explícitamente cuando finaliza el proceso.
El siguiente caso de prueba mínimo muestra el comportamiento que describe:
#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
muestra 5 bloques asignados de funciones llamadas por pthread_exit()
que no está liberado pero aún se puede acceder al salir del proceso. Si el pthread_exit(0);
se reemplaza por return 0;
, los 5 bloques no están asignados.
Sin embargo, si prueba crear y unir una gran cantidad de subprocesos, encontrará que la cantidad de memoria no liberada en uso al salir no aumentar. Esto, y el hecho de que todavía es accesible, indica que solo está viendo una rareza en la implementación de glibc. Varias funciones de glibc asignan memoria con malloc()
la primera vez que se les llama, que se mantienen asignados durante el resto de la vida útil del proceso. glibc no se molesta en liberar esta memoria al salir del proceso, ya que sabe que el proceso se está desmantelando de todos modos; solo sería una pérdida de ciclos de CPU.
¿Estás usando realmente C++, por casualidad? Para aclarar, su archivo fuente termina con un .c
extensión, y la está compilando con gcc
, no g++
?
Parece razonablemente probable que su función esté asignando recursos que espera que se limpien automáticamente cuando regrese la función. Objetos locales de C++ como std::vector
o std::string
haga esto, y sus destructores probablemente no se ejecutarán si llama a pthread_exit
, pero se limpiaría si regresas.
Mi preferencia es evitar las API de bajo nivel como pthread_exit
, y siempre regrese de la función de subproceso, cuando sea posible. Son equivalentes, excepto que pthread_exit
es una construcción de control de flujo de facto que omite el idioma que está utilizando, pero return
no.