C++ 多线程的错误和如何避免(10)
线程中的异常可以使用 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

浙公网安备 33010602011771号