参考我之前关于GDB没有查明SIGSEGV点的问题,
我的线程代码如下:
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);
}
Run Code Online (Sandbox Code Playgroud)
主要代码:
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);
}
Run Code Online (Sandbox Code Playgroud)
编辑:在跑步者线程代码中有一个退出(0),使故障消失.
堆栈损坏背后的原因是什么?
GDB输出:(0xb7fe2b70是转轮线程ID)
LEAVING...
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7fe2b70 (LWP 2604)]
0x00000011 in ?? ()
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
编写一个新的源文件,其main函数与main您在此处发布的内容完全相同,只是使用pthread_create调用函数.看看您是否可以独立于使用线程重新创建问题.从事物看起来你的信号量应该仍然可以在单线程环境中正常工作.
如果仍然失败,您将更容易调试它.
既然你说调用exit而不是返回并没有产生错误,那就表明你已经破坏了runner启动时堆栈上的返回地址.通过调用exit你不依赖于这个内存区域来获取一个退出函数(如果你已经返回了pthread_exit,那么已经被调用的pthread库代码调用了runner).我认为valgrind输出不是100%准确 - 不是由于valgrind中的任何错误,而是因为你触发错误的地方加上你触发的错误类型使得很难确定谁叫什么.
gcc您可能感兴趣的一些标志:
-fstack-protector-all -Wstack-protector
Run Code Online (Sandbox Code Playgroud)
如果没有-f选项,则警告选项不起作用.
您可能还想尝试:
-fno-omit-frame-pointer
Run Code Online (Sandbox Code Playgroud)