c++ - gcc 是否支持带 -fexceptions 的 -static-libgcc?

标签 c++ linux gcc pthreads

我的程序因试图展开堆栈的段错误而崩溃。这是一个 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/

相关文章:

c++ - boost 单元测试 : adding a helper method or private function

c++ - 为什么这个函数指针失败了?

Linux PCIe 驱动程序对 MSI 有周期性的长延迟

linux - 如何在 shell 中重复破折号(连字符)

c++ - 国际象棋骑士到达棋盘上某个位置的最小步骤数

c++ - XCode 不会从文件中获取输入

java - Quartz Scheduler 测试场景不工作

gcc - 由GCC创建的exe文件没有权限?

c++ - std::basic_regex<char32_t>,有人已经尝试了吗?

c++ - 如何永久覆盖 HOMEBREW_CC 和 HOMEBREW_CXX 设置?