简体   繁体   中英

How do I return a struct from a thread?

I'm trying to learn how to return some value from a thread, but i don't get success. I've considered in my code that I can't return a global variable so I get memory from malloc , but I evidently have a problem in pthread_join .

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

struct DIRECCION{
    char street [20];
    int number;
}   ;



struct DIRECCION * pd = NULL;

void* show(void* dm){

    struct DIRECCION * di = (void*)dm;
    pd=(struct DIRECCION*)malloc(sizeof(struct DIRECCION));
    printf("\nHilo show\n");
    printf("Calle: %s\t",di->street);
    printf("Altura: %d\n",di->number);

    printf("Calle: ");
    scanf("%s",pd->street);
    printf("Altura: ");
    scanf("%d",&(pd->number));
    printf("me jui\n");


    return((void*)pd);
}



int main (void){

    pthread_t s_id;
    struct DIRECCION dm;
    struct DIRECCION  d ;


    printf("\nProceso\n");
    printf("Calle: ");
    scanf("%s",dm.street);
    printf("Altura: ");
    scanf("%d",&(dm.number));


    pthread_create( &s_id , NULL, (void*)&show, (void*)&dm);
    pthread_join( s_id , (void*)&d );

    printf("Calle: %s\t",(d.street));
    printf("Altura: %d\n",(d.number));
    free(pd);
    return 0;
}

First step -- get rid of all the casts. You don't need them, and they hide the errors you would otherwise get from the compiler that tell you exactly what you are doing wrong.

When you do that, you see immediately that the problem is your call to pthread_join -- you're trying to call it with a struct DIRECCION * when it needs a void ** . To fix it, you need to pass a void ** , which means you need a void * to take the address of:

void *tmp;
struct DIRECCION *d;
pthread_join( s_id , &tmp );
d = tmp;
... do stuff with d->whatever

In your thread function you have:

pd=(struct DIRECCION*)malloc(sizeof(struct DIRECCION));
return((void*)pd);

Which is saying to return the address of the memory you allocated. Then, in your main function,

struct DIRECCION  d ;
pthread_join( s_id , (void*)&d );

Which is saying to write the value returned by you thread function to the memory where d is stored. In other words, what you're writing to d is a struct DIRECCION* , not a struct DIRECCION .

Try something like

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

struct DIRECCION{
  char street [20];
  int number;
}   ;

void* show(void* dm){
  struct DIRECCION * pd = NULL;
  struct DIRECCION * di = (void*)dm;
  pd=(struct DIRECCION*)malloc(sizeof(struct DIRECCION));
  printf("\nHilo show\n");
  printf("Calle: %s\t",di->street);
  printf("Altura: %d\n",di->number);

  printf("Calle: ");
  scanf("%s",pd->street);
  printf("Altura: ");
  scanf("%d",&(pd->number));
  printf("me jui\n");

  return((void*)pd);
}

int main (void){
  pthread_t s_id;
  struct DIRECCION dm;
  struct DIRECCION*  d ;


  printf("\nProceso\n");
  printf("Calle: ");
  scanf("%s",dm.street);
  printf("Altura: ");
  scanf("%d",&(dm.number));


  pthread_create( &s_id , NULL, (void*)&show, (void*)&dm);
  pthread_join( s_id , (void**)&d );

  printf("Calle: %s\t",(d->street));
  printf("Altura: %d\n",(d->number));
  free(d);
  return 0;
}

The code in show() is OK, aside

  • all those casts, which are completely useless in C.
  • and the fact that pd is defined globally

     struct DIRECCION * pd = NULL; void* show(void* dm) { ... 

    which is not required. Defined pd locally to show() :

     void* show(void* dm) { struct DIRECCION * pd = dm; ... 

In main() a clean way to pull the pointer value returned by show() would be:

int main(void)
{
  ...

  {
    void * pv;
    pthread_join(s_id, &pv);

    /* Find the value inside pv here. */
  }

Doing as above there are two possibilities to go on with the pointer value retrieved fro pthread_join() :

  • Use the pointer value as is like so:

     int main(void) { struct DIRECCION * pd; ... { void * pv; pthread_join(s_id, &pv); pd = pv; } printf("Calle: %s\\t", pd->street); ... 
  • Dereference the pointer value and copy what it points to into suitable structure (the memory it points to is not needed afterwards, so free it to a avoid a leak):

     int main(void) { struct DIRECCION d; ... { void * pv; pthread_join(s_id, &pv); d = *((struct DIRECCION *) pv); /* The only cast necessary in fact. */ free(pv); /* This frees what has been allocated in `show()`. */ } printf("Calle: %s\\t", d.street); ... 

Please note that pthread_join() may fail, so it is strongly recommended to test the value it returns for failure.

If pthread_join() succeeded the pointer-value it returns may still be NULL , so testing this is essential before dereferencing the pointer value.

So a safe way to (try to) pull the pointer value from pthread_join() would be:

int main(void)
{
  ...

  {
    void * pv;
    int result = pthread_join(s_id, &pv);
    if (0 != result)
    {
      fprintf("pthread_join() failed: %s\n", strerror(result));
      exit(EXIT_FAILURE); /* EXIT_x come with stdlib.h. */
    }

    if (NULL == pv)
    {
      /* Handle this case here or exit() as well. */
    }
    else
    {
      /* Use the value inside pv here. */
    }
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM