2010-02-12 93 views
40

我是C新手,并且想用线程来玩一下。我想从使用pthread_exit()如何从C中的线程返回一个值

我的代码线程返回一些值如下:

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

void *myThread() 
{ 
    int ret = 42; 
    pthread_exit(&ret); 
} 

int main() 
{ 
    pthread_t tid; 
    void *status; 

    pthread_create(&tid, NULL, myThread, NULL); 
    pthread_join(tid, &status); 

    printf("%d\n",*(int*)status); 

    return 0; 
} 

我希望节目输出“42 \ n”,但它输出的随机数。我怎样才能打印返回的值?

编辑: 根据第一个答案,问题是我正在返回指向本地变量的指针。返回/存储多个线程变量的最佳做法是什么?全局散列表?

在此先感谢

+1

响应于编辑:我会倾向于如果我需要提供多个线程使用的阵列,每个具有一个地方写它们的结果。如果您事先不知道您要创建多少个线程的上限,那么我通常会认为这是一个问题。但是一般来说,任何结构都可以,只要启动线程的人可以确保线程存储其结果的位置;线程被告知在哪里存储它;谁加入线程可以恢复结果,如果有必要释放它。如果线程以相同的值退出,它将作为参数传递,这可以提供帮助。 – 2010-02-12 12:08:42

回答

34

您正在返回局部变量的地址,该变量在线程函数退出时不再存在。无论如何,为什么要调用pthread_exit?为什么不简单地从线程函数返回一个值?

void *myThread() 
{ 
    return (void *) 42; 
} 

,然后在主:

printf("%d\n",(int)status); 

如果需要返回一个复杂的值这样的结构,它可能比较容易通过的malloc动态分配它(),并返回一个指针。当然,启动线程的代码将负责释放内存。

+1

如果你的意思是“为什么不是”,那么原因不是将42投射到指针类型是未定义的行为。当然,如果它做了什么坏事,它就是其中的一个“这是一个C实现,吉姆,但不是我们所知道的”时刻。 – 2010-02-12 11:49:07

+0

@Steve有时候我会冒险一点UB - 这是其中之一 - 替代品如此混乱。 – 2010-02-12 11:50:31

+0

我也是,但我不会把“随身携带的任何地方”贴纸放在盒子上。 – 2010-02-12 11:51:13

3

我认为你必须在堆上存储数字。 int ret变量在堆栈中并在函数myThread执行结束时被破坏。

void *myThread() 
{ 
     int *ret = malloc(sizeof(int)); 
     if (ret == NULL) { 
      // ... 
     } 
     *ret = 42; 
     pthread_exit(ret); 
} 

不要忘记free它时,你不需要它:)

另一种解决方案是返回数字作为指针的值,如尼尔·巴特沃思建议。

+0

pthread_exit只接受指针作为参数是很愚蠢的:( – 2010-02-12 11:42:15

+3

它不是“笨”,它是C类型系统的限制。为了通过pthreads系统返回一个任意类型的参数,你需要一个Python风格对象系统,其中变量没有类型,只有值可以,或者你需要很多C++模板技术,完全一样,你只能从线程入口点返回'void *',你不能return(eg)double。 – 2010-02-12 12:04:26

+1

另外不要忘记,检查'malloc'工作:-) – 2014-10-23 20:16:36

25

您已经返回了指向局部变量的指针。即使线程没有涉及,这也很糟糕。

执行此操作的常用方法是,当启动的线程与连接的线程相同时,将作为pthread_create的第四个参数将指针传递给由调用方管理的位置中的int。然后这成为线程入口点的(唯一)参数。您可以(如果你喜欢)使用线程退出值来表示成功:

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

int something_worked(void) { 
    /* thread operation might fail, so here's a silly example */ 
    void *p = malloc(10); 
    free(p); 
    return p ? 1 : 0; 
} 

void *myThread(void *result) 
{ 
    if (something_worked()) { 
     *((int*)result) = 42; 
     pthread_exit(result); 
    } else { 
     pthread_exit(0); 
    } 
} 

int main() 
{ 
    pthread_t tid; 
    void *status = 0; 
    int result; 

    pthread_create(&tid, NULL, myThread, &result); 
    pthread_join(tid, &status); 

    if (status != 0) { 
     printf("%d\n",result); 
    } else { 
     printf("thread failed\n"); 
    } 

    return 0; 
} 

如果你绝对要使用的结构线出口值,那么你就必须动态地分配它(并确保谁加入线程释放它)。虽然这并不理想。

+2

我刚刚发现了这一点,但根据http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_exit .html你不需要在线程的函数调用中使用pthread_exit。 “线程终止的正常机制是从启动它的pthread_create()调用中指定的例程返回。pthread_exit()函数提供了线程终止的功能,无需从启动例程返回该线程,从而提供类似于exit()的功能。“ pthread_exit应该用于提前终止。 – 2014-08-27 04:05:21

+1

'printf(“thread failed \ n”);' - 我会用'fprintf'将错误信息打印到'stderr'。 – 2015-12-28 05:56:35

2

您正在返回参考ret这是一个变量在堆栈上。

1

问题:返回/存储多线程变量的最佳做法是什么?全局散列表?

这完全取决于你想要返回什么以及如何使用它?如果你只想返回线程的状态(比如线程是否完成了它想做的事情),那么就使用pthread_exit或者使用return语句从线程函数返回值。

但是,如果你想要一些更多的信息将被用于进一步处理,那么你可以使用全局数据结构。但是,在这种情况下,您需要通过使用适当的同步原语来处理并发问题。或者您可以分配一些动态内存(最好是用于存储数据的结构)并通过pthread_exit发送,并且一旦线程加入,就会在另一个全局结构中更新它。通过这种方式,只有一个主线程会更新全局结构并解决并发问题。但是,您需要确保释放由不同线程分配的所有内存。

0

如果您对返回地址感到不舒服,并且只有一个变量,例如。一个返回的整数值,你甚至可以在传递它之前将它转换为(void *),然后当你在main中收集它时,再次将它转换为(int)。你有价值而不会抛出丑陋的警告。

11

这是一个正确的解决方案。在这种情况下,tdata被分配在主线程中,并且线程有一个空间来放置其结果。

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

typedef struct thread_data { 
    int a; 
    int b; 
    int result; 

} thread_data; 

void *myThread(void *arg) 
{ 
    thread_data *tdata=(thread_data *)arg; 

    int a=tdata->a; 
    int b=tdata->b; 
    int result=a+b; 

    tdata->result=result; 
    pthread_exit(NULL); 
} 

int main() 
{ 
    pthread_t tid; 
    thread_data tdata; 

    tdata.a=10; 
    tdata.b=32; 

    pthread_create(&tid, NULL, myThread, (void *)&tdata); 
    pthread_join(tid, NULL); 

    printf("%d + %d = %d\n", tdata.a, tdata.b, tdata.result); 

    return 0; 
} 
+0

这是最干净的例子 - 我很惊讶它没有更高的优先级。特别是它表明,在调用级别管理存储是正确的事情 - 同时指针可以用于传递更复杂的结构 - 无论是进出。 – Floris 2017-04-11 13:03:05

2
#include<stdio.h> 
#include<pthread.h> 
void* myprint(void *x) 
{ 
int k = *((int *)x); 
printf("\n Thread created.. value of k [%d]\n",k); 
//k =11; 
pthread_exit((void *)k); 

} 
int main() 
{ 
pthread_t th1; 
int x =5; 
int *y; 
pthread_create(&th1,NULL,myprint,(void*)&x); 
pthread_join(th1,(void*)&y); 
printf("\n Exit value is [%d]\n",y); 
} 
+0

从线程函数返回局部变量的值。而不使用全局变量。 – Abhishek 2014-11-18 08:14:24