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)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享