1

私のコード (以下を参照) は奇妙な動作をします。出力は次のとおりです。

Testing whether there are problems with concurrency ...rc is 0. i is 0
.rc is 0. i is 0
.rc is 3. i is 1
.rc is 0. i is 0
.rc is 3. i is 1
.rc is 3. i is 2
.rc is 0. i is 0
.rc is 3. i is 1
.rc is 3. i is 2
.rc is 3. i is 3
.rc is 0. i is 0
.rc is 3. i is 1
.rc is 3. i is 2
.rc is 3. i is 3
.rc is 3. i is 4
.rc is 0. i is 0
Segmentation fault (core dumped)

デバッグしようとしましたが、pthread_join の直後に i が 0 にリセットされていることがわかりました。これは、変更がどこかで行われなければならないという結論に私を導きます。しかし、私はものを見つけることができません。これは本当に難しいコードではないので、ちょっとばかげているように感じます。私は何に気付かなかったのですか?

オペレーティング システムは Ubuntu 14.04 です。N_THREADS は現在 10 に設定されており、N_RUNS は 10000 です。

メインスレッド:

pthread_t threads[N_THREADS];
pthread_attr_t attr;
int i;
int rc;
int status;

printf("Testing whether there are problems with concurrency ...");

pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

for (i = 0; i < N_THREADS; i++){
  if (i) {
    rc = pthread_create(&(threads[i]), &attr, addRemove, 0);
  } else {
    rc = pthread_create(&(threads[i]), &attr, readStuff, 0);
  }
  if (rc) return rc;
}

for(i = 0; i < N_THREADS; i++) {
  rc = pthread_join(threads[i], (void*) &status);
//  if(rc == 3) 
      printf("rc is %d. i is %d\n", rc, i);
//  if (rc) return rc;
  if (status) return status;
  printf(".");
}

pthread_attr_destroy(&attr);

return 0;

ワーカー スレッド:

void* readStuff(void* a)
{
  int i;
  for (i = 0; i< N_RUNS; i++){
  ;
  }
  pthread_exit((void*)0);
}

void* addRemove(void* a)
{
   int i;
   for (i = 0; i< N_RUNS; i++){
   ;
   }
   pthread_exit((void*)0);
}

メインスレッドと上記のコードで作成されたもの以外に、他のスレッドはありません。

コンパイル可能な例

4

1 に答える 1

2

あなたの問題はにあると思いますpthread_join。マニュアルページから:

       int pthread_join(pthread_t スレッド、void **retval);
       ...

       retval が NULL でない場合、pthread_join() は tar の終了ステータスをコピーします。
       get thread (つまり、ターゲットスレッドが提供した値)
       pthread_exit(3)) を *retval が指す場所に配置します。もし対象が
       スレッドがキャンセルされた場合、PTHREAD_CANCELED が *retval に配置されます。

これは が指すものを(64 ビットではサイズ 8)void **で上書きすることを意味します。ほとんどのプラットフォームでサイズ 4 のオブジェクトへのポインタである(ie )を渡しています。retvalvoid *int *&status

そのため、pthread_joinメモリを上書きします。代わりに、関数プロトタイプに従って として宣言statusします。void *

あなたもテストしていstatusます。ここで何を達成しようとしているのかわかりません。

一般に、でコンパイルすると、-Wallこれらのエラーが表示されます。

于 2015-02-11T09:23:13.643 に答える