【问题标题】:Does gcc support -static-libgcc with -fexceptions?gcc 是否支持带有 -fexceptions 的 -static-libgcc?
【发布时间】:2018-05-15 10:42:58
【问题描述】:

我的程序在尝试展开堆栈时因段错误而崩溃。这是 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

【问题讨论】:

  • FWIW 这也与 Clang 一起崩溃。如果我们将文件构建为 C++(通过-x c++ 或通过重命名文件),它也不会崩溃。
  • 对我来说,回溯中的??位置在_Unwind_ForcedUnwind_Phase2
  • 通常-fexceptions-frtti 都被指定。但我不清楚这是否会有所帮助。我觉得libgcc 需要使用相同的选项构建(假设不是)。
  • @jww 根据 GCC,-frtti 不允许用于 C 代码(编译为)

标签: c++ linux gcc pthreads


【解决方案1】:

当使用-fexception 编译时,pthread_exit() 会抛出一个___forced_unwind 异常来强制所有函数展开,这保证了自动存储(又名堆栈)清理。这是因为pthread_exit() 旨在不返回。来自man pthread_exit

这个函数不会返回给调用者。

另一方面,根据man pthread_cleanup_push

POSIX.1 表示使用 return、break、continue 或 goto 过早地离开一个块括起来的 pthread_cleanup_push() 并且 pthread_cleanup_pop() 未定义。便携式应用程序应该 避免这样做。

POSIX 没有提及 C++ 异常,因为 POSIX 只关心 C,但这是有根据的猜测,即在 pthread_cleanup_push()pthread_cleanup_pop() 之间抛出异常会导致未定义的行为。

【讨论】:

    猜你喜欢
    • 2015-10-04
    • 1970-01-01
    • 1970-01-01
    • 2012-10-21
    • 1970-01-01
    • 1970-01-01
    • 2020-12-22
    • 2015-11-13
    • 2020-06-17
    相关资源
    最近更新 更多