当一个exception在multithreadingC ++ 11程序中未处理时会发生什么?
如果我有一个C ++ 11程序运行两个线程,其中一个抛出一个未处理的exception,会发生什么? 整个程序会不会是一场火热的死亡? 请问抛出exception的线程是否会死亡(如果是的话,我能否在这种情况下获得exception)? 还有其他的东西吗?
没有什么真的改变。 在n3290的措辞是:
如果找不到匹配的处理程序,则调用
std::terminate()
函数
terminate
的行为可以用set_terminate
来定制,但是:
所需的行为 :
terminate_handler
应该终止程序的执行而不返回给调用者。
所以程序在这种情况下退出,其他线程不能继续运行。
由于似乎有exception传播的合法兴趣,这至less有点相关的问题,这里是我的build议: std::thread
将被视为一个不安全的原始,以build立如更高层次的抽象。 正如我们所表明的那样,如果在我们刚刚启动的线程中发生exception,那么所有的事情都会爆炸。 但是,如果在启动std::thread
的线程中发生exception,我们可能会遇到麻烦,因为std::thread
的析构函数要求*this
要么被连接要么被分离(或者等价地, 不成为线程 ) 。 违反这些要求导致…调用std::terminate
!
std::thread
危险的代码映射:
auto run = [] { // if an exception escapes here std::terminate is called }; std::thread thread(run); // notice that we do not detach the thread // if an exception escapes here std::terminate is called thread.join(); // end of scope
当然,有些人可能会争辩说,如果我们简单地detach
每一个我们发起的线程,那么我们在第二点就是安全的。 问题是,在某些情况下, join
是最明智的做法。 快速sorting的“天真”并行化需要等到子任务结束。 在这些情况下, join
成为一个同步原语(rendez-vous)。
对我们来说幸运的是,我提到的那些更高层次的抽象确实存在,并且与标准库一起出现。 它们是std::async
, std::future
以及std::packaged_task
, std::promise
和std::exception_ptr
。 上面的等效的exception安全版本:
auto run = []() -> T // T may be void as above { // may throw return /* some T */; }; auto launched = std::async(run); // launched has type std::future<T> // may throw here; nothing bad happens // expression has type T and may throw // will throw whatever was originally thrown in run launched.get();
而事实上,不是调用async
调用的线程,而是将降压传递给另一个线程:
// only one call to get allowed per std::future<T> so // this replaces the previous call to get auto handle = [](std::future<T> future) { // get either the value returned by run // or the exception it threw future.get(); }; // std::future is move-only std::async(handle, std::move(launched)); // we didn't name and use the return of std::async // because we don't have to