Tidak yakin apakah Anda masih tertarik dengan ini, tetapi saat ini saya sedang men-debug situasi yang serupa. Utas yang menggunakan pthread_exit
menyebabkan valgrind melaporkan blok yang dapat dijangkau. Alasannya tampaknya dijelaskan dengan cukup baik di sini:
https://bugzilla.redhat.com/show_bug.cgi?id=483821
Pada dasarnya sepertinya pthread_exit
menyebabkan dlopen
yang tidak pernah dibersihkan secara eksplisit saat proses keluar.
Kasus uji minimal berikut menunjukkan perilaku yang Anda jelaskan:
#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
menunjukkan 5 blok yang dialokasikan dari fungsi yang dipanggil oleh pthread_exit()
yang tidak dibebaskan tetapi masih dapat dijangkau saat proses keluar. Jika pthread_exit(0);
diganti dengan return 0;
, 5 blok tidak dialokasikan.
Namun, jika Anda menguji membuat dan menggabungkan sejumlah besar utas, Anda akan menemukan bahwa jumlah memori yang tidak dibebaskan yang digunakan saat keluar tidak meningkat. Ini, dan fakta bahwa itu masih dapat dijangkau, menunjukkan bahwa Anda hanya melihat keanehan dari penerapan glibc. Beberapa fungsi glibc mengalokasikan memori dengan malloc()
pertama kali mereka dipanggil, yang tetap dialokasikan untuk sisa masa pakai proses. glibc tidak repot-repot membebaskan memori ini saat keluar dari proses, karena glibc tahu bahwa prosesnya tetap dirobohkan - itu hanya akan membuang-buang siklus CPU.
Apakah Anda benar-benar menggunakan C++? Untuk memperjelas - file sumber Anda diakhiri dengan .c
ekstensi, dan Anda mengompilasinya dengan gcc
, bukan g++
?
Tampaknya cukup masuk akal bahwa fungsi Anda mengalokasikan sumber daya yang Anda harapkan akan dibersihkan secara otomatis saat fungsi kembali. Objek C++ lokal seperti std::vector
atau std::string
lakukan ini, dan destruktornya mungkin tidak akan dijalankan jika Anda memanggil pthread_exit
, tetapi akan dibersihkan jika Anda baru saja kembali.
Preferensi saya adalah menghindari API tingkat rendah seperti pthread_exit
, dan selalu kembali dari fungsi utas, jika memungkinkan. Mereka setara, kecuali bahwa pthread_exit
adalah konstruk kontrol aliran de-facto yang memintas bahasa yang Anda gunakan, tetapi return
tidak.