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 指针。

这是一个简单的示例,我正在尝试开始工作,以便能够完成我正在尝试创建的另一个程序,其中我将有一个线程数组,每个线程都计算一个浮点值,并且我想使用 pthread_exit 和 pthread_join 将这些计算值中的每一个存储到一个浮点数组中,但我真的不知道如何将 pthread_join 中的值存储到一个数组中。

4

2 回答 2

5

pthread_exit需要一个void*,而不是一个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);
}

这感觉有点骇人听闻,因为确实如此。如果您确定在您将要瞄准的每个平台上进行往返转换void*将保留 a 的价值,那么请务必放弃。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) 制作一个结构来封装线程的所有输入/输出参数(重量级,但非常明确):

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

只需添加另一种方法来避免所有警告。通过阅读多个 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 回答