如果在生成 std::thread 后引发,则未捕获异常

Exception not caught if raised after spawning std::thread

本文关键字:捕获异常 thread std 如果      更新时间:2023-10-16

我对异常的奇怪行为感到困惑,这些异常在生成另一个线程后被抛出在主线程中:

void thread_body(){
while(true) cout << "in thread" << endl;
}
int main(int argc, char** argv)
{
try{
auto t = std::thread( thread_body );
throw std::runtime_error("error!");
t.join();
} catch (const std::exception& e) {
cout << e.what() << endl;
}
}

输出为:

in thread
in thread
in thread
terminate called without an active exception
The program has unexpectedly finished.

如果我在生成这样的线程之前抛出:

throw std::runtime_error("error!");
auto t = std::thread( thread_body );

比正常捕获:

错误!

为什么在第一种情况下没有捕获异常?我应该怎么做才能以通常的方式捕捉它?

当抛出异常时,线程对象将被销毁。但是线程析构函数将在它仍然可连接时被调用。这会导致调用terminate,因此永远不会调用异常处理程序。

此外,在没有正确同步的情况下从不同线程写入标准流不是一个好主意。

好的,经过一些研究,我找到了这个问题的解决方案。必须将线程包装到类中并创建其实例,而不是创建原始线程。在析构函数中,可以检查线程是否仍然可连接,并在可能的情况下执行操作以优雅地停止线程主体。在这种情况下,当抛出异常时,析构函数将在线程仍在运行时被调用,它将整理事情。