线程中出现异常

Exceptions in threads

本文关键字:异常 线程      更新时间:2023-10-16

如果一个线程中发生异常,如果该线程中没有捕获到该异常,主线程会受到影响吗?

为什么?据我记忆所及,异常是基于堆栈的,所以当发生异常时,堆栈会展开,对吗?但是,如果一个线程有自己的堆栈,为什么主线程会受到影响?

示例:

#include <iostream>
#include <thread>
#include <chrono>
int main()
{
    std::thread([]{
        throw std::runtime_error("HELLO");
    }).detach();
    std::this_thread::sleep_for(std::chrono::seconds(5));
}

此线程已分离。我不明白为什么主程序会崩溃。对我来说,这就像一个子进程崩溃,导致父进程崩溃。。

:S有人能解释线程中的异常是如何工作的吗?

根据MSDN(http://msdn.microsoft.com/en-us/library/ac9f67ah.aspx),如果没有找到合适的catch处理程序,则将调用terminate函数。默认情况下,terminate调用C运行时函数abort,但如果需要,可以通过调用set_terminate来覆盖此函数。

在多线程场景中,terminate将在该辅助线程中调用,这将导致程序退出,即主/父/入口线程将立即停止,进程将被操作系统终止。

将线程与进程进行比较是不公平的——进程之间是内存隔离的,而线程则不是。如果程序处于意外或不希望的状态,则可能会引发异常,这意味着程序内存空间中的数据可能已损坏,重要的是程序正确处理异常,否则终止(以避免将损坏的数据写入磁盘的风险,这是一件非常糟糕的事情(TM))。我认为这解释了在任何线程不处理异常的情况下使用程序abort的动机,因为如果主线程继续执行,它可能会对损坏或无效的数据进行操作,而这是您不希望的。

这与C#等其他平台中的情况相同(除了它不是terminate,而是AppDomain.UnhandledException,并且是可恢复的),尽管Java是一个显著的例外(并非双关语),线程将终止,但进程将继续运行——我想(警告:推测!)在Java的情况下,因为内存本身不会损坏,所以允许进程继续运行没有那么大的危害,即使应用程序对象状态可能已损坏。