在线程中,如果产生了异常,没有捕获处理的话,系统会直接调用std::terminate终止进程的。因为一个线程的异常,导致整个进程终止,是不太划算的。因此,尽量保证线程运行中异常能够被处理。
线程异常被单独拿出来说,说明它还是有一点麻烦的。不能想当然去处理。下面是一段想当然的常见错误处理。
// 错误样例
int main() {
try {
thread t([]() {
cout << "this will crash!" << endl;
string s;
char c = s.at(2);
});
t.join();
} catch (...) {
cout << "catched the exception!" << endl;
}
return 0;
}
执行结果如下:
这是因为主线程中是抓不到其他线程的异常的。
所以,简单的做法是每个线程自己保证安全,自己在内部try catch。改造一下代码
int main() {
thread t([]() {
try {
cout << "this will crash!" << endl;
string s;
char c = s.at(2);
} catch (out_of_range &e) {
cout << "catched the exception:" << e.what() << endl;
}
});
t.join();
cout << "happy ending!" << endl;
return 0;
}
结果如下
可是你希望在主线程能够捕获到这个线程的异常,那么该怎么办呢?
稍微麻烦点。需要通过全局变量或者静态变量将子线程中的异常保存,然后在主线程中rethrow-try-catch。
代码如下:
exception_ptr eptr = nullptr;
int main() {
thread t([]() {
cout << "this will crash!" << endl;
try {
string s;
char c = s.at(2);
} catch (...) {
eptr = current_exception();
cout << "catched the exception!" << endl;
}
});
t.join();
try {
if (eptr) {
cout << "rethrow exception!" << endl;
rethrow_exception(eptr);
}
} catch (exception &e) {
cout << "the exception is " << e.what()<< endl;
}
cout << "happy ending!" << endl;
return 0;
}
结果如下