Search code examples
cmultithreadingpthreadssegmentation-faultdouble-pointer

Accessing the return value using pthread_exit()


I have done the following code.

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

struct foo
{
   int a;
   int b;
};

void* thread_func1(void *arg)
{
   struct foo *temp = (struct foo*)malloc(sizeof(struct foo));

   temp->a = 10;
   temp->b = 20;

   pthread_exit(temp);
}

void* thread_func2(void *arg)
{
   pthread_exit((void*)100);
}

int main()
{
   pthread_t tid1, tid2;
   int err;
   struct foo *f;
   void *ret;

   err = pthread_create(&tid1, NULL, thread_func1, NULL);
   err = err | pthread_create(&tid2, NULL, thread_func2, NULL);

   if(err != 0)
   {
      perror("pthread_create()");
      exit(-1);
   }

   err = pthread_join(tid1, (void**)&f);
   if(err != 0 )
   {
      perror("pthread_join1");
      exit(-1);
   }

   printf("a = %d, b = %d\n", f->a, f->b); //Line1

   err = pthread_join(tid2, &ret);
   if(err != 0 )
   {
      perror("pthread_join2");
      exit(-1);
   }

   printf("ret = %d\n", *(int*)ret); //Line2

   return 0;

}

I get segmentation fault on Line2. What is wrong with Line2

If i modify Line2 to

printf("ret = %d\n", (int)ret);

there is no segmentation fault and it prints the correct value(ie, 100). I do not understand why the modification works. I believe i have the wrong concept regarding the usage of double pointers. I would like to get it corrected.

What is the reason for the Segmentation fault and why the modification works?


Solution

  • You return one number from the thread. In the first thread, that number is a struct foo *. Therefore, if you say

    pthread_join(tid1, &ret);
    

    then ret will contain that pointer (which is not a double pointer).

    Similarly in the second case, you are returning 100 even though you are looking at it as if it's a void *. Nevertheless, the value is still 100!

    Therefore when you write

    pthread_join(tid2, &ret);
    

    ret will contain 100, which is not a pointer, but a mere integer. That is why you should also cast it to int.

    The reason you got a segmentation fault is that you look at 100 as an int * and then try to dereference it.