无法理解段错误的情况。
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函数中使用指针和动态分配以正确方式执行时)。
请帮帮我。 提前谢谢。
答案 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 *然后返回所需的整数类型是完全正常的。您只是不希望将实际指针传递给您打算取消引用的堆栈上的数据,因为您将调用未定义的行为。在一天结束时,指针只不过是一个无符号整数,其值通常指向内存中的某个位置。