web-dev-qa-db-ja.com

pthread_create()の使用中に構造体を引数として渡す

pthread_create()を次のように使用しながら、4番目の引数として構造体を渡してみました。

pthread_create(&tid1, NULL, calca, &t); //t is the struct

これで、構造体の変数(t.a、t.b、またはt.c)にアクセスしようとすると、エラーが発生し続けます。構造体または共用体ではないもののメンバーを要求します。

構造体をスレッドに渡すために使用できる代替方法は何ですか?

17
skinderneath

おそらく、pthread_createと同じスコープで構造を作成しています。この構造は、そのスコープが終了すると無効になります。

ヒープ上の構造体へのポインターを作成し、その構造体ポインターをスレッドに渡してみてください。そのメモリをどこかで削除することを忘れないでください(二度と使用しない場合、または不要になった場合はスレッド内)。

また、cyberconteが述べたように、異なるスレッドからそのデータにアクセスする場合は、ミューテックスまたはクリティカルセクションを使用してデータへのアクセスをロックする必要があります。

2009年5月14日編集@ 12:19 PM EST:また、他の人が言及しているように、パラメーターを正しいタイプにキャストする必要があります。

グローバル構造(主張しているように見える)である変数を渡す場合、スレッド関数は次のタイプにキャストする必要があります。

void my_thread_func(void* arg){
    my_struct foo = *((my_struct*)(arg)); /* Cast the void* to our struct type */
    /* Access foo.a, foo.b, foo.c, etc. here */
}

または、構造体へのポインタを渡す場合:

void my_thread_func(void* arg){
    my_struct* foo = (my_struct*)arg; /* Cast the void* to our struct type */
    /* Access foo->a, foo->b, foo->c, etc. here */
}
24

スレッド関数内にいる場合、渡す引数はvoid *です。そのまま使用する前に、構造体にキャストする必要があります。

void my_thread_func(void* arg){
    my_struct foo = (my_struct)(*arg); /* Cast the void* to our struct type */
    /* Access foo.a, foo.b, foo.c, etc. here */
}
2
Harper Shelby
  1. セマフォを作成する

  2. 構造体へのポインタとセマフォハンドルで構成される別の構造体を作成します

  3. この新しい構造体へのポインターをpthread_createに渡します

  4. 親スレッド、つまりpthread_createと呼ばれるスレッドでは、セマフォを待ちます

  5. 子スレッドで、構造体のメンバーをローカル変数にコピーするか、別の場所に保存します

  6. 子スレッドで、セマフォに信号を送ります

  7. 親スレッドで、セマフォを閉じます

1
dmityugov

my_struct foo =(my_struct)(* arg); incoreectですmy_struct * foo =(my_struct *)(arg);を試してください。
AND、int関数を呼び出して、スレッドが静的であることを確認します(つまり、ポイントされているメモリが霧の中で失われないようにします)

0
user3512266

このエラーメッセージは、ポインタを逆参照していないことを意味します。

「t-> a」ではなく「t.a」と言っている

 [me @ myhost〜] $ cat testitx.c 
 struct x {
 int a、b; 
}; 
 
 int main(int argc、char * argv [])
 {
 struct xy、* z; 
 
 z =&y; 
 za = 10; 
} 
 [me @ myhost〜] $ cc -c testitx.c 
 testitx.c:関数 `main ':
 testitx.c :10:エラー:構造体または共用体ではないもののメンバー `a 'の要求
 [me @ myhost〜] $ 
0
smcameron

以前は他の回答に記載されているのと同じ間違いを犯すことがよくありましたが、今では少し異なるアプローチを取り、エラーの可能性をスレッド関数からpthread_create呼び出しに移しています。

スレッド関数を「通常の」方法で宣言および定義します。

void *ThreadFunction(sPARAMETERS *Params) {

  // do my threading stuff...

}

そして、pthread_createを呼び出すときは、キャストを使用する必要があります。

pthread_create(&ThreadId,0,(void*(*)(void*)) &ThreadFunction,&Params);

Paramsで&を使用することを忘れることはほとんどありません。コンパイラーは、もう一方の端で犯した間違いをすべて処理します。コールバックにも最適です。

0
Marc Bernier

共有メモリまたはグローバル変数(他にその引数が必要ない場合)、またはこれらがデータをフィードしているスレッドである場合はリンクリストを使用できます。

スレッド共有されている変数をロックすることを忘れないでください。

しかし、実際の問題のあるコードがなければ、現在の実装で何が間違っているのかを伝えることはできません。

0
cyberconte