【问题标题】:Why can't use ** to get return value of pthread_join为什么不能用**来获取pthread_join的返回值
【发布时间】:2017-02-10 14:52:50
【问题描述】:

我昨天使用pthread_join函数遇到问题,出现编译错误,我在网上搜索了很久,但没有解决。

pthread_join.c:

#include  <stdio.h>

#include  <pthread.h>

void* say_hello(void* args)
{

    printf("hello from thread\n");
    pthread_exit((void*)1);
}

int main()
{

    pthread_t tid;
    int iRet=pthread_create(&tid,NULL,say_hello,NULL);
    if(iRet)
    {
            printf("pthread create error:iRet=%n\n",iRet);
            return iRet;
    }

    void *retval;
    iRet=pthread_join(tid,&retval);
    if(iRet)
    {
            printf("pthread_join error:iRet=%d\n",iRet);
            return iRet;
    }


       printf("retval=%ld\n",(long)**(&retval));
      // printf("retval=%ld\n",(long)retval); 
       return 0;
}

错误:

 $ error:invalid use of void expression

我尝试使用(&amp;retval) 来获得pthread_join 的返回值。我觉得 retval 属于 void** ,然后我使用 (retval) 应该可以获取值,但是失败了。我不能使用 void 来获取 ** 指针的值,我猜retval是pthread_join的值,但是如果用**retval获取,就不能成功。

我用gcc编译它,它会显示:

  $ error:invalid use of void expression       

【问题讨论】:

    标签: c linux gcc pthreads pthread-join


    【解决方案1】:

    引用此评论:Why can't use ** to get return value of pthread_join 此处的另一个答案。

    这个

      ...
    
      pthread_exit((void*) 1);
    }
    

    可能会导致陷阱条件并由此导致未定义的行为。

    因此,在线程终止时返回 1 值的正确方法是:

      ...
    
      int * pi = malloc(sizeof *pi);
      /* Add error checking an handling for malloc() here. */
      *pi = 1;
    
      pthread_exit(pi); /* No need to cast in C. */
    }
    

    在线程内加入另一个线程做:

      ...
    
      {
        void * pv;
        pthread_join(..., &pv); /* Add error checking and handling for pthread_join(). */ 
    
        printf("thread returned: %d\n", *((int*) pv));
    
        free(pv); /* Free what the other thread allocated (see above). */
      }     
    
      ...
    

    【讨论】:

      【解决方案2】:

      为什么不能用**来获取pthread_join的返回值

      void *retval;
      ...
      printf("retval=%ld\n",(long)**(&retval));
      

      retvalvoid*&amp;retvalvoid**,所以 **(&amp;retval)void。然后,您尝试将void 转换为long,这是不可能的。这就是你从 gcc 获得的原因:error:invalid use of void expression

      posix 线程启动例程必须返回void* 类型的值。在say_hello() 中,您返回一个int (1),根据需要正确转换为void*

      pthread_join(pthread_t thread, void **value_ptr) 需要void* 的地址作为第二个参数来存储连接线程的返回值。通过调用pthread_join(tid,&amp;retval),您正确地向pthread_join() 提供retval 的地址,即void*。这样做,线程返回值(void*)1 存储到retval

      现在,如果您想打印返回值 retval,转换为 long,正确的语法是您注释掉的那个:

      printf("retval=%ld\n",(long)retval);
      

      你也可以这样写:

      printf("retval=%ld\n",(long)*(&retval));
      

      虽然没有多大意义,但这是等价的......

      【讨论】:

      • 为什么可以使用void*存储返回值,void*是指针,是地址,地址可以存储值?我不明白。
      • @Marcos: void* 通常表示内存地址但不一定;在函数say_hello() 中,您将int (1) 转换为void*,这意味着您使用void* 来存储int 值,因此它不代表有效的内存地址。所以是的,指针可以存储不是地址的值。
      • @Marcos 是的,它旨在使用指针来存储返回值。你不能通过*ptr 取消引用它,你只能打印指针的值。为什么要使用指针?从表面上看,使用指针,您可以返回“有限整数值”或**指向结构的指针**(一石二鸟)。要彻底理解这一点,您可能需要检查这些函数的实现,这对我来说太难了。
      猜你喜欢
      • 2016-06-02
      • 2020-08-06
      • 2014-12-23
      • 2012-03-18
      • 2021-10-26
      • 1970-01-01
      • 2012-10-30
      • 2020-08-15
      • 2019-01-08
      相关资源
      最近更新 更多