news 2026/4/18 8:37:45

线程函数中抛出的未捕获异常

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
线程函数中抛出的未捕获异常

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

      • 崩溃原因分析
      • 修复后的完整代码
      • 关键修改说明
      • 运行结果示例
      • 总结

#include<iostream>#include<thread>#include<mutex>#include<vector>#include<stdexcept>intg_count=0;std::mutex g_mutex;voidincrementSafe(inttimes){for(inti=0;i<times;++i){// RAII:构造时加锁,析构时解锁(即使异常也会解锁)std::lock_guard<std::mutex>lock(g_mutex);// 模拟异常if(i==500){// 异常抛出时,lock的析构函数会被调用,自动解锁throwstd::runtime_error("意外异常");}g_count++;}}intmain(){constintthread_num=5;constinttimes_per_thread=1000;std::vector<std::thread>threads;try{for(inti=0;i<thread_num;++i){threads.emplace_back(incrementSafe,times_per_thread);}for(auto&t:threads){t.join();}}catch(conststd::exception&e){std::cout<<"捕获异常:"<<e.what()<<std::endl;}std::cout<<"最终count值:"<<g_count<<std::endl;return0;}

上篇文章中代码运行崩溃

崩溃原因分析

这段代码崩溃的核心原因是:线程函数中抛出的未捕获异常无法被主线程的catch捕获
C++ 线程的规则是:如果线程函数内部抛出异常且没有在线程内捕获,该异常会直接触发std::terminate()函数,导致整个程序强制终止(崩溃),主线程的try-catch完全无法拦截这种跨线程的异常。

虽然std::lock_guard的 RAII 特性确实能保证异常时解锁(这部分是正确的),但异常本身没有被处理,最终导致程序崩溃。

修复后的完整代码

下面是修复后的代码,核心思路是在线程函数内部捕获异常,避免异常逃逸出线程;同时保留原有的线程安全和 RAII 锁特性:

#include<iostream>#include<thread>#include<mutex>#include<vector>#include<stdexcept>intg_count=0;std::mutex g_mutex;voidincrementSafe(inttimes){try{// 线程内部捕获异常,避免异常逃逸for(inti=0;i<times;++i){// RAII:构造时加锁,析构时解锁(即使异常也会解锁)std::lock_guard<std::mutex>lock(g_mutex);// 模拟异常if(i==500){throwstd::runtime_error("意外异常");}g_count++;}}catch(conststd::exception&e){// 线程内处理异常,也可以记录日志、通知主线程等std::lock_guard<std::mutex>lock(g_mutex);// 加锁保证输出线程安全std::cout<<"线程内捕获异常:"<<e.what()<<std::endl;}}intmain(){constintthread_num=5;constinttimes_per_thread=1000;std::vector<std::thread>threads;// 创建并启动所有线程for(inti=0;i<thread_num;++i){threads.emplace_back(incrementSafe,times_per_thread);}// 等待所有线程执行完成for(auto&t:threads){if(t.joinable()){// 检查线程是否可join,避免重复joint.join();}}std::cout<<"最终count值:"<<g_count<<std::endl;return0;}

关键修改说明

  1. 线程内增加try-catch:在incrementSafe函数开头添加try块,捕获函数内抛出的所有异常,避免异常逃逸出线程导致程序崩溃;
  2. 线程安全的异常输出:异常信息输出时也加了互斥锁,避免多个线程同时输出导致乱码;
  3. 增加joinable()检查:防止因异常导致线程状态异常时重复join,提升代码健壮性;
  4. 移除主线程多余的try-catch:因为线程内的异常已被处理,主线程无需再捕获(如果需要主线程感知异常,可以用std::future,新手阶段先掌握线程内捕获即可)。

运行结果示例

运行后你会看到类似这样的输出(顺序可能因线程调度略有不同):

线程内捕获异常:意外异常 线程内捕获异常:意外异常 线程内捕获异常:意外异常 线程内捕获异常:意外异常 线程内捕获异常:意外异常 最终count值:2500

(每个线程执行到第500次时抛出异常,所以每个线程只执行了500次计数,5个线程总计 5×500=2500)

总结

  1. 核心崩溃原因:线程内未捕获的异常会触发std::terminate(),无法被主线程catch拦截;
  2. 关键修复手段:在线程函数内部捕获并处理异常,是新手阶段最稳妥的方式;
  3. RAII 锁的价值:即使抛出异常,std::lock_guard也会自动析构解锁,不会导致死锁,这部分原代码的设计是正确的。

如果需要让主线程感知到线程内的异常(而非仅在线程内处理),可以基于std::packaged_taskstd::future实现,你有需要的话我可以补充这部分代码。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/17 2:56:03

基于springboot的就业推荐系统

文章目录详细视频演示项目介绍技术介绍功能介绍核心代码系统效果图源码获取详细视频演示 文章底部名片&#xff0c;获取项目的完整演示视频&#xff0c;免费解答技术疑问 项目介绍 基于SpringBoot的就业推荐系统具有广泛的应用前景和推广价值。它可以应用于高校就业指导中心、…

作者头像 李华
网站建设 2026/4/11 19:20:34

寒假学习(8)(c语言8+模数电8)

对于STM32F103C8T6集成版进行小升级&#xff0c;加入了光敏电阻&#xff0c;热敏电阻&#xff0c;8个小灯&#xff0c;两个按键&#xff0c;macial口改成了type-c&#xff0c;然后改成了自动下载 然后为了省钱又全部改成直插式的了 #include <stdio.h> #include <std…

作者头像 李华
网站建设 2026/4/18 2:09:18

设计客户需求整理工具,录入客户沟通内容,自动提取核心需求,异议点及诉点,生成需求清单,标注优先级,帮销售/运营精准对接客户需求。

1. 实际应用场景与痛点 场景 - 销售/运营在与客户沟通后&#xff0c;需要整理客户需求、异议点和诉求&#xff0c;以便后续跟进。 - 沟通记录通常是语音、聊天记录或笔记&#xff0c;信息杂乱&#xff0c;难以快速提炼重点。 - 手工整理耗时&#xff0c;容易遗漏关键信息。 痛…

作者头像 李华
网站建设 2026/4/18 6:24:47

长尾关键词优化对SEO效果提升的重要性与实践技巧

在数字营销的领域中&#xff0c;长尾关键词优化不仅是提升SEO效果的重要环节&#xff0c;也是吸引精准流量的有效手段。长尾关键词通常由三个到五个词组成&#xff0c;能够明确捕捉用户意图&#xff0c;尤其适合那些有特定需求的用户。通过精确选择并合理布局这些关键词&#x…

作者头像 李华
网站建设 2026/4/18 8:37:27

基于深度学习YOLOv8的道路坑洼识别检测系统(YOLOv8+YOLO数据集+UI界面+Python项目源码+模型)

一、项目介绍 摘要 本项目基于YOLOv8目标检测算法&#xff0c;开发了一套专门用于道路坑洼识别的智能检测系统。该系统能够通过实时图像或视频流自动检测并定位道路表面的坑洼、裂缝等缺陷&#xff0c;为道路维护、交通安全和智慧城市建设提供数据支持。项目采用了一个包含3,…

作者头像 李华
网站建设 2026/4/18 4:31:44

人工智能之数字生命-查找方法的方法的讨论

一、先给结论(直接回答你问的) 1️⃣ 方法节点里的条件节点和结果节点要不要共用一个场景节点? 结论:是“同源但不共用指针”。 逻辑上: 结果场景 = 条件场景 + 方法动作的变化 结构上: 必须是两个独立的场景节点树 但它们来源于同一个“抽象场景模板” 👉 换句话说:…

作者头像 李华