参考我之前关于GDB not pinpointing the SIGSEGV point的问题,
我的线程代码如下:
void *runner(void *unused)
{
do
{
sem_wait(&x);
...
if(/*condition 1 check*/)
{
sem_post(&x);
sleep(5);
sem_wait(&x);
if(/*repeat condition 1 check; after atleast 5 seconds*/)
{
printf("LEAVING...\n");
sem_post(&x);
// putting exit(0); here resolves the dilemma
return(NULL);
}
}
sem_post(&x);
}while(1);
}
主要代码:
sem_t x;
int main(void)
{
sem_init(&x,0,1);
...
pthread_t thrId;
pthread_create(&thrId,NULL,runner,NULL);
...
pthread_join(thrId,NULL);
return(0);
}
编辑:在跑步者线程代码中有一个退出(0),使故障消失。
堆栈损坏背后的原因是什么?
GDB输出:(0xb7fe2b70是跑步者线程ID)
LEAVING...
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7fe2b70 (LWP 2604)]
0x00000011 in ?? ()
Valgrind输出:
==3076== Thread 2:
==3076== Jump to the invalid address stated on the next line
==3076== at 0x11: ???
==3076== by 0xA26CCD: clone (clone.S:133)
==3076== Address 0x11 is not stack'd, malloc'd or (recently) free'd
==3076==
==3076==
==3076== Process terminating with default action of signal 11 (SIGSEGV)
==3076== Bad permissions for mapped region at address 0x11
==3076== at 0x11: ???
==3076== by 0xA26CCD: clone (clone.S:133)
==3076== Address 0x11 is not stack'd, malloc'd or (recently) free'd
答案 0 :(得分:7)
使用main
函数编写一个新的源文件,其功能与您在此处发布的main
完全相同,只是使用pthread_create
调用该函数。看看您是否可以独立于使用线程重新创建问题。从事物看起来你的信号量应该仍然可以在单线程环境中正常工作。
如果仍然失败,您将更容易调试它。
由于您说调用exit
而不是返回没有产生错误,因此建议您在runner
启动时损坏堆栈上的返回地址。通过调用exit
,您不依赖于此内存区域来访问一个退出函数(如果您已经返回pthread_exit,则会调用已调用runner
的pthread库代码)。我认为valgrind输出不是100%准确 - 不是由于valgrind中的任何错误,而是因为你触发错误的地方加上你触发的错误类型使得很难确定谁叫什么
您可能感兴趣的一些gcc
标志:
-fstack-protector-all -Wstack-protector
如果没有-f选项,警告选项不起作用。
您可能还想尝试:
-fno-omit-frame-pointer
答案 1 :(得分:2)
代码中缺少所有重要部分,但是堆栈损坏的最常见原因是:
char buffer[20]
并在边界外写(sprintf
是一种很棒的方法来实现它。)答案 2 :(得分:1)
使用valgrind或等效的内存检查工具来搞清楚。 别猜了。也停止发布不完整的代码,特别是如果你不知道它是否有问题。该错误可能在此功能之外。例如,可能信号量未初始化。
从valgrind输出中,我可以建议你的pthread_create()
行必须包含无效的函数指针。所以pthread会跳转到那个假地址,然后崩溃。显然没有堆栈......