pthread_join()上的分段错误

时间:2012-07-26 18:38:58

标签: segmentation-fault

无法理解段错误的情况。

int main()
{
     int val;
     pthread_t thread;
 ...........................
     pthread_join(thread,(void **) &val);  
     printf("Val=%d",val);   
 //and here sometimes come segmentation 
 //fault and other times i get correct val value

 ...........................
}

void *Do(void *)
{
    int retval=4;
...............
    pthread_exit((void *) retval);
}

如果我是正确的,pthread_exit()将addres(值为4)存储到由(& val)指针指向的变量中,这意味着在pthread_join()之后val = 4。 但是,如果我多次启动程序,我得到了正确的val值(即4)和不同启动时的分段错误。 (顺便说一句,当在Do函数中使用指针和动态分配以正确方式执行时)。

请帮帮我。 提前谢谢。

2 个答案:

答案 0 :(得分:0)

我唯一能想到的是,你正在返回函数* Do的局部变量的地址。局部变量存储在为函数分配的堆栈框架中。您将返回指向线程终止后无效的位置的指针。

见:
http://man7.org/linux/man-pages/man3/pthread_exit.3.html

在哪里说:

  

retval指向的值不应该位于调用上   线程的堆栈,因为该堆栈的内容在之后是未定义的   线程终止。

答案 1 :(得分:0)

pthread_exit((void *) retval);

这需要一个整数(具有未确定的大小)并将其强制转换为具有可能不同大小的指针。我会说大多数时候这很好,因为sizeof(void *)> = sizeof(int)。

pthread_join(thread,(void **) &val); 

这个调用实际上只有在sizeof(int)== sizeof(void *)时才有效。如果您使用的是64位系统,则& val指向4个字节的空间,但是您告诉编译器它指向8.如果此地址位于正确的位置(在分配的虚拟地址空间的末尾),那么它将在pthread_join中尝试写入void指针。

你应该做的是:

void *retval;
pthread_join(thread, (void **), &retval);
val = (int)retval;

指向int的指针将截断任何更重要的位。此外,如果它是一个64位大端系统,你永远不会得到正确的val,因为实际存储数据的4个字节是第二个4字节。

与其他答案相反,将整数返回值传递回void *然后返回所需的整数类型是完全正常的。您只是不希望将实际指针传递给您打算取消引用的堆栈上的数据,因为您将调用未定义的行为。在一天结束时,指针只不过是一个无符号整数,其值通常指向内存中的某个位置。