1. ホーム
  2. c

[解決済み] pthread_exit vs. return

2022-02-05 07:19:26

質問

以下のように定義された結合可能なpthreadランナー関数があります。

void *sumOfProducts(void *param)
{
...
pthread_exit(0);
}

このスレッドはメインスレッドに参加することになっています。

私のプログラムをValgrindで実行すると、いつも次のようなメッセージが表示されました。 以下のようなリーク :

LEAK SUMMARY:
   definitely lost: 0 bytes in 0 blocks
   indirectly lost: 0 bytes in 0 blocks
     possibly lost: 0 bytes in 0 blocks
   still reachable: 968 bytes in 5 blocks
        suppressed: 0 bytes in 0 blocks

ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 15 from 10)

pthreadsのマニュアルページを確認したところ、こう書いてありました。

  The new thread terminates in one of the following ways:

   * It  calls  pthread_exit(3),  specifying  an exit status value that is
     available  to  another  thread  in  the  same  process   that   calls
     pthread_join(3).

   * It  returns  from  start_routine().   This  is  equivalent to calling
     pthread_exit(3) with the value supplied in the return statement.

   * It is canceled (see pthread_cancel(3)).

   * Any of the threads in the process calls exit(3), or the  main  thread
     performs  a  return  from main().  This causes the termination of all
     threads in the process.

奇跡的に、pthread_exit()をreturn文に置き換えたところ。 漏れがなくなった .

return(NULL);

実際の質問は3つあります。

  1. return文がリークしなかった理由を誰か説明してください。
  2. 両者の間には、スレッドからの終了に関して、何か根本的な違いがあるのでしょうか?
  3. もしそうなら、どのような場合に一方を他方より優先させるべきでしょうか?

どのように解決するのですか?

以下の最小限のテストケースは、あなたが説明した動作を示します。

#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 が呼び出した関数から割り当てられた5つのブロックを示しています。 pthread_exit() はアンフリーですが、プロセス終了時にまだ到達可能です。 もし pthread_exit(0); に置き換えます。 return 0; 5ブロックは確保されません。

しかし、大量のスレッドを作成して結合するテストを行うと、終了時に使用中の解放されていないメモリの量が ない が増加します。 このことと、まだ到達可能であることから、glibcの実装の奇妙な点を見ているだけであることがわかります。 glibcのいくつかの関数は、メモリを malloc() glibc はプロセスの終了時にこのメモリを解放することを気にしません。