少司缘:心之所向,爱无疆界

核心内容摘要

孟若羽夏晴子三部曲:一场跨越时空的爱恋与抉择
罗宾的秘密武器:草帽海贼团的“解毒”日常

idg5527:开启智能时代,驭见无限可能

提示文章写完后目录可以自动生成如何生成可参考右边的帮助文档文章目录崩溃原因分析修复后的完整代码关键修改说明运行结果示例

总结#includeiostream#includethread#includemutex#includevector#includestdexceptintg_count0;std::mutex g_mutex;voidincrementSafe(inttimes){for(inti0;itimes;i){// RAII构造时加锁析构时解锁即使异常也会解锁std::lock_guardstd::mutexlock(g_mutex);// 模拟异常if(i

{// 异常抛出时lock的析构函数会被调用自动解锁throwstd::runtime_error(意外异常);}g_count;}}intmain(){constintthread_num5;constinttimes_per_thread1000;std::vectorstd::threadthreads;try{for(inti0;ithread_num;i){threads.emplace_back(incrementSafe,times_per_thread);}for(autot:threads){t.join();}}catch(conststd::exceptione){std::cout捕获异常e.what()std::endl;}std::cout最终count值g_countstd::endl;return0;}上篇文章中代码运行崩溃崩溃原因分析这段代码崩溃的核心原因是线程函数中抛出的未捕获异常无法被主线程的catch捕获。

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

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

修复后的完整代码下面是修复后的代码核心思路是在线程函数内部捕获异常避免异常逃逸出线程同时保留原有的线程安全和 RAII 锁特性#includeiostream#includethread#includemutex#includevector#includestdexceptintg_count0;std::mutex g_mutex;voidincrementSafe(inttimes){try{// 线程内部捕获异常避免异常逃逸for(inti0;itimes;i){// RAII构造时加锁析构时解锁即使异常也会解锁std::lock_guardstd::mutexlock(g_mutex);// 模拟异常if(i

{throwstd::runtime_error(意外异常);}g_count;}}catch(conststd::exceptione){// 线程内处理异常也可以记录日志、通知主线程等std::lock_guardstd::mutexlock(g_mutex);// 加锁保证输出线程安全std::cout线程内捕获异常e.what()std::endl;}}intmain(){constintthread_num5;constinttimes_per_thread1000;std::vectorstd::threadthreads;// 创建并启动所有线程for(inti0;ithread_num;i){threads.emplace_back(incrementSafe,times_per_thread);}// 等待所有线程执行完成for(autot:threads){if(t.joinable()){// 检查线程是否可join避免重复joint.join();}}std::cout最终count值g_countstd::endl;return0;}关键修改说明线程内增加try-catch在incrementSafe函数开头添加try块捕获函数内抛出的所有异常避免异常逃逸出线程导致程序崩溃线程安全的异常输出异常信息输出时也加了互斥锁避免多个线程同时输出导致乱码增加joinable()检查防止因异常导致线程状态异常时重复join提升代码健壮性移除主线程多余的try-catch因为线程内的异常已被处理主线程无需再捕获如果需要主线程感知异常可以用std::future新手阶段先掌握线程内捕获即可。

运行结果示例运行后你会看到类似这样的输出顺序可能因线程调度略有不同线程内捕获异常意外异常 线程内捕获异常意外异常 线程内捕获异常意外异常 线程内捕获异常意外异常 线程内捕获异常意外异常 最终count值2500每个线程执行到第500次时抛出异常所以每个线程只执行了500次计数5个线程总计 5×5002500

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

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

美女班长求被-美女班长求被应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123