我的程序因试图展开堆栈的段错误而崩溃。这是一个 gcc 错误还是不允许选项 -fexceptions
和 -static-libgcc
的组合?
如果发生以下情况,则不会发生崩溃:
-static-libgcc
省略-fexceptions
省略编译链接一步完成pthread_cleanup_push()
和pthread_cleanup_pop()
省略- 使用
g++
或gcc -x g++
完成编译 (*)
我已经在 gcc 4.8.4 和 4.8.5 上试过了。
(*) 这不适用于我们基于 gcc 4.2.3 的自定义构建环境之一。然而,对于同样基于 gcc 4.2.3 的不同版本的构建环境,崩溃根本不会发生!
测试用例
/*
* thread_crash.c: Test case for thread unwinder crash bug.
*
* Compile (with native or V6p3, 32 or 64 bit) using:
* gcc -o thread_crash.o -c thread_crash.c -ggdb -Wall -pthread -fexceptions
* g++ -o thread_crash thread_crash.o -ggdb -Wall -lpthread -static-libgcc
*
* Expected behaviour: No output.
* Observed behaviour: Outputs "Aborted (core dumped)".
*/
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <signal.h>
static void cleanup(void *ptr)
{
}
void *child(void *ptr)
{
pthread_cleanup_push(cleanup, NULL);
pthread_exit(NULL);
pthread_cleanup_pop(1);
return NULL;
}
int main()
{
pthread_t foo;
pthread_create(&foo, NULL, child, NULL);
pthread_join(foo, NULL);
return 0;
}
来自 gdb 的回溯
#0 0x00007ffff72271f7 in raise () from /lib64/libc.so.6
#1 0x00007ffff72288e8 in abort () from /lib64/libc.so.6
#2 0x00000000004031be in _Unwind_SetGR ()
#3 0x000000000040587a in __gcc_personality_v0 ()
#4 0x00007ffff6feba14 in ?? () from /lib64/libgcc_s.so.1
#5 0x00007ffff6febd64 in _Unwind_ForcedUnwind () from /lib64/libgcc_s.so.1
#6 0x00007ffff7bcd240 in __pthread_unwind () from /lib64/libpthread.so.0
#7 0x00007ffff7bc7e35 in pthread_exit () from /lib64/libpthread.so.0
#8 0x0000000000400a97 in child (ptr=0x0) at thread_crash.c:46
#9 0x00007ffff7bc6e25 in start_thread () from /lib64/libpthread.so.0
#10 0x00007ffff72ea34d in clone () from /lib64/libc.so.6
最佳答案
当使用-fexception
编译时,pthread_exit()
抛出一个___forced_unwind
异常强制所有函数展开,这保证了自动存储(又名堆栈)清理。这是因为 pthread_exit()
被设计为不返回。来自 man pthread_exit
:
This function does not return to the caller.
另一方面,根据man pthread_cleanup_push
:
POSIX.1 says that the effect of using return, break, continue, or goto to prematurely leave a block bracketed pthread_cleanup_push() and pthread_cleanup_pop() is undefined. Portable applications should avoid doing this.
POSIX 没有提到 C++ 异常,因为 POSIX 只关心 C,但这是一个有根据的猜测,即在 pthread_cleanup_push()
和 pthread_cleanup_pop()
之间抛出异常会导致未定义的行为。
关于c++ - gcc 是否支持带 -fexceptions 的 -static-libgcc?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50348211/