C++ 多线程的错误和如何避免(10)

2022/5/23 1:04:10

本文主要是介绍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



这篇关于C++ 多线程的错误和如何避免(10)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程