これにまだ興味があるかどうかはわかりませんが、現在、同様の状況をデバッグしています。 pthread_exit
を使用するスレッド valgrind が到達可能なブロックを報告するようにします。その理由はここでかなりよく説明されているようです:
https://bugzilla.redhat.com/show_bug.cgi?id=483821
基本的には pthread_exit
のようです dlopen
を引き起こします プロセスの終了時に明示的にクリーンアップされることはありません。
次の最小限のテスト ケースは、あなたが説明した動作を示します:
#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
pthread_exit()
によって呼び出された関数から割り当てられた 5 つのブロックを示します これは解放されていませんが、プロセスの終了時にまだ到達可能です。 pthread_exit(0);
の場合 return 0;
に置き換えられます 、5 つのブロックが割り当てられていません。
ただし、多数のスレッドの作成と結合をテストすると、終了時に使用されている解放されていないメモリの量が そう ないことがわかります。 増加。これと、まだ到達可能であるという事実は、glibc 実装の奇妙さを見ているだけであることを示しています。いくつかの glibc 関数は malloc()
でメモリを割り当てます 最初に呼び出されたとき、残りのプロセスの存続期間に割り当てられたままになります。 glibc は、プロセスが破棄されていることを認識しているため、プロセスの終了時にこのメモリを解放することはしません。CPU サイクルの浪費になるだけです。
もしかして、あなたは実際に C++ を使っていますか?明確にするために、ソースファイルは .c
で終わります 拡張機能であり、gcc
でコンパイルしています 、 g++
ではありません ?
関数が返されたときに自動的にクリーンアップされると予想されるリソースを関数が割り当てている可能性がかなり高いようです。 std::vector
などのローカル C++ オブジェクト または std::string
これを行うと、 pthread_exit
を呼び出すと、デストラクタが実行されない可能性があります 、しかし、あなたが戻るだけで片付けられます。
pthread_exit
などの低レベル API は避けるのが私の好みです 、可能な場合は常にスレッド関数から戻ります。 pthread_exit
以外は同等です は、使用している言語をバイパスする事実上のフロー制御構造ですが、 return