メインコンテンツ

結合済みまたは分離済みスレッドの結合または分離

以前に結合または分離されたスレッドの再結合または再分離

説明

このチェッカーは、既定の Polyspace® as You Code 解析では非アクティブにされますPolyspace as You Code 解析で非アクティブにされるチェッカー (Polyspace Access)を参照してください

この欠陥は、以下の場合に発生します。

  • 以前に結合または分離されたスレッドを結合しようとする。

  • 以前に結合または分離されたスレッドを分離しようとする。

[結果の詳細] ペインには、そのスレッドが以前に結合または分離されたかどうかが表示されます。また、それまでの関連するイベントも表示されます。

たとえば、thrd_join で結合されたスレッドは、thrd_detach で分離されます。

thrd_t id;
...
thrd_join(id, NULL);
thrd_detach(id);

スレッドが結合済みと見なされるのは、以前のスレッド結合が成功した場合のみです。たとえば、次の if 分岐ではスレッドは結合済みと見なされません。

thrd_t t;
...
if (thrd_success != thrd_join(t, 0)) {
    /* Thread not considered joined */
}
関数 thrd_current() などを使用して結合済みスレッドを分離させる場合、解析では検出できません。

リスク

C11 規格 (7.26.5.3 節および 7.26.5.6 節) では、結合または分離したことのあるスレッドを結合または分離してはならないと規定しています。規格のこれらの節に違反することは未定義の動作になります。

修正方法

以前に結合または分離されたスレッドは結合しないようにします。既に結合または分離されたスレッドは分離しないようにします。

すべて展開する

#include <stddef.h>
#include <threads.h>
#include <stdlib.h>


extern int thread_func(void *arg);

int main (void)
{
  thrd_t t;

  if (thrd_success != thrd_create (&t, thread_func, NULL)) {
    /* Handle error */
    return 0;
  }

  if (thrd_success != thrd_join (t, 0)) {   
    /* Handle error */
    return 0;
  }

  if (thrd_success != thrd_detach (t)) {   
    /* Handle error */
    return 0;
  }

  return 0;
}

この例では、以前に thrd_join で結合されたスレッドに対して thrd_detach を使用しているため、未定義の動作を発生させてしまいます。

この例で Bug Finder 実行時のコンパイル エラーを回避するには、オプション [C 標準バージョン] (-c-version) を使用して C11 規格を指定します。

修正 – 結合済みスレッドの分離を回避

前の thrd_join ステートメントまたは後続の thrd_detach ステートメントを削除します。この訂正されたバージョンでは、thrd_detach ステートメントが削除されています。

#include <stddef.h>
#include <threads.h>
#include <stdlib.h>


extern int thread_func(void *arg);

int main (void)
{
  thrd_t t;

  if (thrd_success != thrd_create (&t, thread_func, NULL)) {
    /* Handle error */
    return 0;
  }

  if (thrd_success != thrd_join (t, 0)) {   
    /* Handle error */
    return 0;
  }

  return 0;
}
#include <stddef.h>
#include <pthread.h>
#define thread_success 0

extern void *thread_func(void *arg);


int main() {
    pthread_t id;
    pthread_attr_t attr;
    
    if(thread_success != pthread_attr_init(&attr)) {
        return 0;
    }
   
    if(thread_success != pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) {
        return 0;
    }
       
    if(thread_success != pthread_create(&id, &attr, thread_func, NULL)) {
            return 0;
    }
    
    if(thread_success != pthread_join(id, NULL)) {
            return 0;
    }

    return 0;    
}

この例では、スレッド属性に状態 PTHREAD_CREATE_DETACHED が割り当てられます。この属性を使用して作成されたスレッドが結合されます。

修正 – 結合可能なスレッドとして作成

1 つの修正方法として、スレッド属性に状態 PTHREAD_CREATE_JOINABLE が割り当てられたスレッドを作成してから、そのスレッドを結合します。

#include <stddef.h>
#include <pthread.h>
#define thread_success 0

extern void *thread_func(void *arg);


int main() {
    pthread_t id;
    pthread_attr_t attr;
    
    if(thread_success != pthread_attr_init(&attr)) {
        return 0;
    }
   
    if(thread_success != pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)) {
        return 0;
    }
       
    if(thread_success != pthread_create(&id, &attr, thread_func, NULL)) {
            return 0;
    }
    
    if(thread_success != pthread_join(id, NULL)) {
            return 0;
    }

    return 0;    
}

結果情報

グループ: 同時実行
言語: C
既定値: オフ
コマンド ライン構文: DOUBLE_JOIN_OR_DETACH
影響度: Medium

バージョン履歴

R2019b で導入