为什么pthread_exit会抛出被省略号捕获的内容?

15

如果被 pthread_create 调用的函数具有以下结构

try{
  ...code....
  pthread_detach(pthread_self());
  pthread_exit(NULL);
}catch(...){
  std::cout<<"I am here"<<std::endl;
}

为什么在执行 pthread_exit 时,省略号的异常处理程序会被调用? (请注意,例如 std::exception 不会被抛出)


你在哪个编译器下看到这个的? - Dave S
@Fabio 或许是堆栈上某个对象的析构函数抛出了异常。 - Torsten Robitzki
@DaveS g++ TorstenRobitzki 谢谢,我也是这么想的,但情况就像 eran 解释的那样。 - Fabio Dalla Libera
1个回答

29

至少在GCC中,pthread_exit可能会抛出一个___forced_unwind异常,用于在线程退出期间展开堆栈。它不继承自std::exception,因此不能像捕获标准异常一样捕获它。如果您确实捕获了该异常,请确保重新throw它以便它能发挥作用:

try {
...
} catch (abi::___forced_unwind&) {
    throw;
} catch (...) {
    // whatever
}
抛出异常的原因是 pthread_exit 被指定为永远不会返回。让它抛出异常可以保证栈分配变量的清理,并且在其位置之后不执行任何代码(除非你捕获 unwind 异常...)。然而这种方法不太便携,例如 Clang 使用完全不同的机制。
顺便说一下,这又是一个典型案例,catch (...) 惯用法做的更多的是伤害而不是好处。它有时被用来"稳定"抛出未知异常的代码。但这只是把问题的可视性推迟到以后的时间和地点,使得很难确定问题的真正起源。在这样的 catch 中唯一合理的做法是进行最小限度的清理、可能的记录,然后重新抛出异常。由于未处理的异常导致进程崩溃并不好看,但它可以提供一个可调试的崩溃转储,清楚地显示了出错的命令。但这只是我的怨恨 catch (...),与 pthread_exit 几乎没有关系...

非常感谢,这正是问题所在! 我猜你的抛出是为了防止 致命错误:异常未被重新抛出 谢谢! - Fabio Dalla Libera
2
@Fabio:abi::__forced_unwind exception 异常也可能在使用 pthread_cancel 取消的线程中抛出。在终止 pthreads 时要小心省略号 catch。 - Tanner Sansbury
非常有趣,但我对了解更多关于__force_unwind很感兴趣,而且2012年的链接已经失效。 - Antoine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接