Ich bin mir nicht sicher, ob Sie noch daran interessiert sind, aber ich debugge derzeit eine ähnliche Situation. Threads, die pthread_exit
verwenden Valgrind veranlassen, erreichbare Blöcke zu melden. Der Grund scheint hier ziemlich gut erklärt zu sein:
https://bugzilla.redhat.com/show_bug.cgi?id=483821
Im Wesentlichen scheint es pthread_exit
zu sein verursacht einen dlopen
die niemals explizit bereinigt wird, wenn der Prozess beendet wird.
Der folgende minimale Testfall zeigt das von Ihnen beschriebene Verhalten:
#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
zeigt 5 Blöcke, die von Funktionen zugewiesen wurden, die von pthread_exit()
aufgerufen wurden das ist nicht freigegeben, aber am Prozessende noch erreichbar. Wenn der pthread_exit(0);
wird durch return 0;
ersetzt , die 5 Blöcke sind nicht belegt.
Wenn Sie jedoch das Erstellen und Verbinden einer großen Anzahl von Threads testen, werden Sie feststellen, dass die Menge an nicht freigegebenem Speicher, die beim Beenden verwendet wird, nicht ist Zunahme. Dies und die Tatsache, dass es immer noch erreichbar ist, weist darauf hin, dass Sie nur eine Kuriosität der glibc-Implementierung sehen. Mehrere glibc-Funktionen weisen Speicher mit malloc()
zu das erste Mal, wenn sie aufgerufen werden, die ihnen für den Rest der Prozesslebensdauer zugewiesen bleiben. glibc macht sich nicht die Mühe, diesen Speicher beim Beenden des Prozesses freizugeben, da es weiß, dass der Prozess ohnehin abgebaut wird - es wäre nur eine Verschwendung von CPU-Zyklen.
Benutzt du zufällig C++? Zur Verdeutlichung - Ihre Quelldatei endet mit einem .c
Erweiterung, und Sie kompilieren sie mit gcc
, nicht g++
?
Es scheint ziemlich wahrscheinlich, dass Ihre Funktion Ressourcen zuweist, von denen Sie erwarten, dass sie automatisch bereinigt werden, wenn die Funktion zurückkehrt. Lokale C++-Objekte wie std::vector
oder std::string
Wenn Sie dies tun, werden ihre Destruktoren wahrscheinlich nicht ausgeführt, wenn Sie pthread_exit
aufrufen , würde aber aufgeräumt werden, wenn Sie einfach zurückkehren.
Ich bevorzuge es, Low-Level-APIs wie pthread_exit
zu vermeiden , und kehren Sie nach Möglichkeit immer nur von der Thread-Funktion zurück. Sie sind äquivalent, außer dass pthread_exit
ist ein De-facto-Flusssteuerungskonstrukt, das die von Ihnen verwendete Sprache umgeht, aber return
nicht.