1

pthread から値を返し、その値をキャッチするという概念を取得しようとしていますが、何が起こっているのか、またはそれを機能させる方法を理解できません。単一のスレッドを作成するこの単純なプログラムがあります。このスレッドは int 値 100 で終了し、pthread_join でその値をキャッチしようとします。

#include <stdio.h>
#include <pthread.h>

void *doStuff(void *param) {
    int a = 100;
    pthread_exit(a);
}

void main() {
    pthread_t thread;
    int a;
    pthread_create(&thread, NULL, doStuff, NULL);
    pthread_join(thread, &a);
    printf("%d\n", a);
}

動作しますが、いくつかの警告が表示されます:

./teste.c: In function ‘doStuff’:
./teste.c:7:2: warning: passing argument 1 of ‘pthread_exit’ makes pointer from integer without a cast [enabled by default]
In file included from ./teste.c:2:0:
/usr/include/pthread.h:241:13: note: expected ‘void *’ but argument is of type ‘int’
./teste.c: In function ‘main’:
./teste.c:17:2: warning: passing argument 2 of ‘pthread_join’ from incompatible pointer type [enabled by default]
In file included from ./teste.c:2:0:
/usr/include/pthread.h:249:12: note: expected ‘void **’ but argument is of type ‘int *’

pthread_exit で void ポインターを返さなければならないと思っていたので、これらの警告が表示される理由がわかりません。正直なところ、これが機能している理由もわかりません。

これは、私が作成しようとしている別のプログラムを完成させることができるように、作業を開始しようとしている簡単な例です。このプログラムには、スレッドの配列があり、それぞれが単一の float 値を計算します。 、および pthread_exit と pthread_join を使用して、これらの計算された値のそれぞれを float の配列に格納したいのですが、pthread_join からの値を配列に格納する方法がよくわかりません。

4

2 に答える 2

5

pthread_exitvoid*ではなくを取りますint。(呼び出しは、スレッド関数からpthread_exit(x)単に戻ることと同じであることに注意してください。)x

int問題の最も簡単な修正は、生成された値を格納するポインタをスレッド関数に渡すことです。

void *doStuff(void *param) {
    int a = 100;
    *(int*)param = a;
    return NULL;
}

int main(void) {
    pthread_t thread;
    int a;
    pthread_create(&thread, NULL, doStuff, &a);
    pthread_join(thread, NULL);
    printf("%d\n", a);
}

編集:結果を伝えるためにスレッド関数の戻り値を本当に使用する必要がある場合は、いくつかのオプションがあります。

(1) 戻り値を の内外にキャストしますvoid*

void *doStuff(void *param) {
    int a = 100;
    return (void*)a;
}

int main(void) {
    pthread_t thread;
    pthread_create(&thread, NULL, doStuff, NULL);
    void* ptr;
    pthread_join(thread, &ptr);
    int a = (int)ptr;
    printf("%d\n", a);
}

これは少しハックな気がします。対象とするすべてのプラットフォームで to-and-from のキャストがvoid*の値を保持することが確実な場合は、必ずキャストを外してください。int

(2) 戻り値を含む、動的に割り当てられたストレージへのポインターを返します。

void *doStuff(void *param) {
    int a = 100;
    int* ptr = malloc(sizeof(*ptr));
    assert(ptr); /* I'm lazy, sue me. */
    *ptr = a;
    return ptr;
}

int main(void) {
    pthread_t thread;
    pthread_create(&thread, NULL, doStuff, NULL);
    void* ptr;
    pthread_join(thread, &ptr);
    int a = *(int*)ptr;
    free(ptr);
    printf("%d\n", a);
}

(3) スレッドのすべての in/out パラメータをカプセル化する構造を作成します (重いですが、適切に明示的です)。

struct foo {
  int input1;
  int input2;
  int result;
};

void *doStuff(void *param) {
    foo* f = param;
    f->result = f->input1 + f->input2;
    return NULL;
}

int main(void) {
    foo* ptr = malloc(sizeof(*ptr));
    assert(ptr);
    ptr->input1 = 5;
    ptr->input2 = 3;

    pthread_t thread;
    pthread_create(&thread, NULL, doStuff, ptr);
    pthread_join(thread, NULL);

    printf("%d\n", ptr->result);
    free(ptr);
}
于 2013-08-09T18:31:35.983 に答える
0

すべての警告を回避する方法をもう 1 つ追加するだけです。複数のSOの回答を読んで、実際にこの解決策を得ました。

void *thread_fn(void *arg) {
    int a = 100;
    return (void*)(intptr_t)a;
}

int main(void) {
    pthread_t thread;
    void* ptr;
    int a;
    pthread_create(&thread, NULL, thread_fn, &a);
    pthread_join(thread, &ptr);
    a = (intptr_t)ptr;
    printf("%d\n", a);
}

上記のコード スニペットでreturn (void*)(intptr_t)a;は、最初に整数を型キャストして、ポインター (intptr_t) と同じサイズの整数型を取得しています。そして、それを void ポインターに型キャストできるようになりました。同じですa = (intptr_t)ptr;

于 2015-05-13T07:22:54.870 に答える