线程中的异常可以使用 std::rethrow_exception 抛给主线程
问题分析:一个线程中抛出的异常是没法被另一个线程捕获的。假如我们在主线程中创建一个子线程,子线程中的函数抛出了异常,主线程的 catch 是不会触发,如下,
#include<iostream> #include<thread> #include<exception> #include<stdexcept> static std::exception_ptr teptr = nullptr; void LaunchRocket() { throw std::runtime_error("Catch me in MAIN"); } int main() { try { std::thread t1(LaunchRocket); t1.join(); } catch (const std::exception &ex) { std::cout << "Thread exited with exception: " << ex.what() << "\n"; } return 0; }
LaunchRocket() 会抛出异常,但是主线程的 catch 不会触发。
如果我们需要在程序崩溃的同时,希望在主线程中做出处理,那可以使用 std::exception_ptr 去捕获异常并抛给后台的线程,比如主线程
步骤:
1. 创建一个全局的 globalExceptionPr 的实例,并初始化为 nullptr
2. 在子线程中抛出异常后,在 catch 代码段将 std::current_exception() 赋值给 globalExceptionPr
3. 在主线程中检查 globalExceptionPr 是否被设置了
4. 如果为真,使用 std::rethrow_exception(exception_ptr p) 重新抛出由 exception_ptr 参数引用的异常
如下为修改后的例子,
#include<iostream> #include<thread> #include<exception> #include<stdexcept> static std::exception_ptr globalExceptionPtr = nullptr; void LaunchRocket() { try { std::this_thread::sleep_for(std::chrono::milliseconds(100)); throw std::runtime_error("Catch me in MAIN"); } catch (...) { //Set the global exception pointer in case of an exception globalExceptionPtr = std::current_exception(); } } int main() { std::thread t1(LaunchRocket); t1.join(); if (globalExceptionPtr) { try { std::rethrow_exception(globalExceptionPtr); } catch (const std::exception &ex) { std::cout << "Thread exited with exception: " << ex.what() << "\n"; } } return 0; }
调试结果:Thread exited with exception: Catch me in MAIN