如何从线程返回结构?

问题描述 投票:1回答:3

我正在尝试学习如何从线程中返回一些值,但我没有获得成功。我在我的代码中考虑过我不能返回一个全局变量,所以我从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;
}
c linux pthreads
3个回答
2
投票

第一步 - 摆脱所有演员阵容。您不需要它们,它们会隐藏您从编译器获得的错误,这些错误会告诉您确切的错误。

当你这样做时,你会立即看到问题是你对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
投票

在你的线程函数中你有:

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

1
投票

除了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. */
    }
  }
© www.soinside.com 2019 - 2024. All rights reserved.