Как мне вернуть структуру из потока? - PullRequest
1 голос
/ 14 апреля 2019

Я пытаюсь узнать, как вернуть какое-то значение из потока, но я не добился успеха.Я учел в своем коде, что не могу вернуть глобальную переменную, поэтому я получаю память из malloc, но у меня, очевидно, есть проблема в 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;
}

Ответы [ 3 ]

2 голосов
/ 14 апреля 2019

Первый шаг - избавиться от всех приведений. Они вам не нужны, и они скрывают ошибки, которые вы могли бы получить от компилятора, которые точно сообщают вам, что вы делаете неправильно.

Когда вы это делаете, вы сразу же видите, что проблема заключается в вашем звонке на pthread_join - вы пытаетесь вызвать его с struct DIRECCION *, когда ему нужно void **. Чтобы исправить это, вам нужно передать void **, что означает, что вам нужно void *, чтобы взять адрес:

void *tmp;
struct DIRECCION *d;
pthread_join( s_id , &tmp );
d = tmp;
... do stuff with d->whatever
1 голос
/ 14 апреля 2019

Код в show() в порядке, кроме

  • все те броски, которые абсолютно бесполезны в C.
  • и тот факт, что pd определяется глобально

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

    что не требуется. Определено pd локально для show():

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

В main() чистый способ получить значение указателя, возвращенное show(), будет:

int main(void)
{
  ...

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

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

Действуя как описано выше, есть две возможности продолжить работу со значением указателя, полученным для pthread_join():

  • Используйте значение указателя, как показано ниже:

    int main(void)
    {
      struct DIRECCION * pd;
      ...
    
      {
        void * pv;
        pthread_join(s_id, &pv);
    
        pd = pv;
      }
    
      printf("Calle: %s\t", pd->street);
    
      ...
    
  • Размените значение указателя и скопируйте то, на что он указывает, в подходящую структуру (память, на которую он указывает, впоследствии не нужна, поэтому освободите ее, чтобы избежать утечки):

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

Обратите внимание, что pthread_join() может завершиться ошибкой, поэтому настоятельно рекомендуется проверить значение, которое оно возвращает для ошибки.

Если pthread_join() преуспел, значение указателя, которое он возвращает, может все еще быть NULL, таким образом, проверка это важно перед разыменованием значения указателя.

Таким образом, безопасный способ (попытка) получить значение указателя из pthread_join() было бы:

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. */
    }
  }
1 голос
/ 14 апреля 2019

В вашей функции потока у вас есть:

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

Что говорит, что возвращает адрес памяти, которую вы выделили.Затем в вашей основной функции

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

, которая говорит о записи значения, возвращенного вашей потоковой функцией, в память, где хранится d.Другими словами, то, что вы пишете d, это struct DIRECCION*, а не struct DIRECCION.

Попробуйте что-то вроде

#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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...