1

无法理解段错误的情况。

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

请帮帮我。先感谢您。

4

2 回答 2

0

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

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

在哪里 说:

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

于 2013-11-15T22:31:28.200 回答
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 * 然后返回所需的整数类型,将整数返回值传回是完全可以的。您只是不想将实际指针传递给您打算取消引用的堆栈上的数据,因为您将调用未定义的行为。归根结底,指针只不过是一个无符号整数,其值通常指向内存中的某个位置。

于 2015-10-27T19:46:07.717 回答