如何从C中返回一个值?

时间:2022-05-27 20:58:17

I'am new to C and would like to play with threads a bit. I would like to return some value from a thread using pthread_exit()

我刚到C,想稍微玩一下。我想从使用pthread_exit()的线程返回一些值

My code is as follows:

我的代码如下:

#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;
}

I would expect the program output "42\n" but it outputs a random number. How can I print the returned value?

我希望程序输出“42\n”,但它输出一个随机数。如何打印返回的值?

EDIT: According to first answers the problem is that I am returning pointer to local variable. What is the best practice of returning/storing variables of multiple threads? A global hash table?

编辑:根据第一个回答,问题是我返回到局部变量的指针。返回/存储多个线程变量的最佳实践是什么?一个全球性的哈希表吗?

Thanks in advance

谢谢提前

8 个解决方案

#1


34  

You are returning the address of a local variable, which no longer exists when the thread function exits. In any case, why call pthread_exit? why not simply return a value from the thread function?

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

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

and then in main:

然后在主:

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

If you need to return a complicated value such a structure, it's probably easiest to allocate it dynamically via malloc() and return a pointer. Of course, the code that initiated the thread will then be responsible for freeing the memory.

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

#2


25  

You've returned a pointer to a local variable. That's bad even if threads aren't involved.

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

The usual way to do this, when the thread that starts is the same thread that joins, would be to pass a pointer to an int, in a location managed by the caller, as the 4th parameter of pthread_create. This then becomes the (only) parameter to the thread's entry-point. You can (if you like) use the thread exit value to indicate success:

通常的方法是,当启动的线程是连接的同一线程时,将会在调用者管理的位置传递一个指向int的指针,作为pthread_create的第4个参数。这将成为线程的入口点的(唯一)参数。您可以(如果您喜欢)使用线程退出值来指示成功:

#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;
}

If you absolutely have to use the thread exit value for a structure, then you'll have to dynamically allocate it (and make sure that whoever joins the thread frees it). That's not ideal, though.

如果您绝对要使用一个结构的线程退出值,那么您就必须动态地分配它(并确保连接线程的任何人都可以释放它)。不过,这并不是理想的。

#3


12  

Here is a correct solution. In this case tdata is allocated in the main thread, and there is a space for the thread to place its result.

这里有一个正确的解决方案。在这种情况下,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;
}

#4


3  

I think you have to store the number on heap. The int ret variable was on stack and was destructed at the end of execution of function myThread.

我认为你必须把数字存储在堆上。int ret变量在堆栈上,在函数myThread执行结束时被销毁。

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

Don't forget to free it when you don't need it :)

当你不需要的时候,别忘了把它释放出来。

Another solution is to return the number as value of the pointer, like Neil Butterworth suggests.

另一种解决方案是返回值作为指针的值,就像Neil Butterworth建议的那样。

#5


2  

You are returning a reference to ret which is a variable on the stack.

您正在返回一个关于ret的引用,它是堆栈上的一个变量。

#6


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);
}  

#7


1  

Question : What is the best practice of returning/storing variables of multiple threads? A global hash table?

问题:返回/存储多个线程的变量的最佳实践是什么?一个全球性的哈希表吗?

This totally depends on what you want to return and how you would use it? If you want to return only status of the thread (say whether the thread completed what it intended to do) then just use pthread_exit or use a return statement to return the value from the thread function.

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

But, if you want some more information which will be used for further processing then you can use global data structure. But, in that case you need to handle concurrency issues by using appropriate synchronization primitives. Or you can allocate some dynamic memory (preferrably for the structure in which you want to store the data) and send it via pthread_exit and once the thread joins, you update it in another global structure. In this way only the one main thread will update the global structure and concurrency issues are resolved. But, you need to make sure to free all the memory allocated by different threads.

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

#8


0  

if you're uncomfortable with returning addresses and have just a single variable eg. an integer value to return, you can even typecast it into (void *) before passing it, and then when you collect it in the main, again typecast it into (int). You have the value without throwing up ugly warnings.

如果你对返回的地址感到不舒服,并且只有一个变量eg。返回的整型值,您甚至可以在传递它之前将其输入(void *),然后当您在main中收集它时,再将它输入到(int)中。你有这个价值,却不抛出丑陋的警告。

#1


34  

You are returning the address of a local variable, which no longer exists when the thread function exits. In any case, why call pthread_exit? why not simply return a value from the thread function?

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

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

and then in main:

然后在主:

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

If you need to return a complicated value such a structure, it's probably easiest to allocate it dynamically via malloc() and return a pointer. Of course, the code that initiated the thread will then be responsible for freeing the memory.

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

#2


25  

You've returned a pointer to a local variable. That's bad even if threads aren't involved.

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

The usual way to do this, when the thread that starts is the same thread that joins, would be to pass a pointer to an int, in a location managed by the caller, as the 4th parameter of pthread_create. This then becomes the (only) parameter to the thread's entry-point. You can (if you like) use the thread exit value to indicate success:

通常的方法是,当启动的线程是连接的同一线程时,将会在调用者管理的位置传递一个指向int的指针,作为pthread_create的第4个参数。这将成为线程的入口点的(唯一)参数。您可以(如果您喜欢)使用线程退出值来指示成功:

#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;
}

If you absolutely have to use the thread exit value for a structure, then you'll have to dynamically allocate it (and make sure that whoever joins the thread frees it). That's not ideal, though.

如果您绝对要使用一个结构的线程退出值,那么您就必须动态地分配它(并确保连接线程的任何人都可以释放它)。不过,这并不是理想的。

#3


12  

Here is a correct solution. In this case tdata is allocated in the main thread, and there is a space for the thread to place its result.

这里有一个正确的解决方案。在这种情况下,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;
}

#4


3  

I think you have to store the number on heap. The int ret variable was on stack and was destructed at the end of execution of function myThread.

我认为你必须把数字存储在堆上。int ret变量在堆栈上,在函数myThread执行结束时被销毁。

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

Don't forget to free it when you don't need it :)

当你不需要的时候,别忘了把它释放出来。

Another solution is to return the number as value of the pointer, like Neil Butterworth suggests.

另一种解决方案是返回值作为指针的值,就像Neil Butterworth建议的那样。

#5


2  

You are returning a reference to ret which is a variable on the stack.

您正在返回一个关于ret的引用,它是堆栈上的一个变量。

#6


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);
}  

#7


1  

Question : What is the best practice of returning/storing variables of multiple threads? A global hash table?

问题:返回/存储多个线程的变量的最佳实践是什么?一个全球性的哈希表吗?

This totally depends on what you want to return and how you would use it? If you want to return only status of the thread (say whether the thread completed what it intended to do) then just use pthread_exit or use a return statement to return the value from the thread function.

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

But, if you want some more information which will be used for further processing then you can use global data structure. But, in that case you need to handle concurrency issues by using appropriate synchronization primitives. Or you can allocate some dynamic memory (preferrably for the structure in which you want to store the data) and send it via pthread_exit and once the thread joins, you update it in another global structure. In this way only the one main thread will update the global structure and concurrency issues are resolved. But, you need to make sure to free all the memory allocated by different threads.

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

#8


0  

if you're uncomfortable with returning addresses and have just a single variable eg. an integer value to return, you can even typecast it into (void *) before passing it, and then when you collect it in the main, again typecast it into (int). You have the value without throwing up ugly warnings.

如果你对返回的地址感到不舒服,并且只有一个变量eg。返回的整型值,您甚至可以在传递它之前将其输入(void *),然后当您在main中收集它时,再将它输入到(int)中。你有这个价值,却不抛出丑陋的警告。