当前位置: 首页 > news >正文

C语言中嵌套捕获异常

在C++中我们可以使用try/catch来捕获异常,但是C语言中没有这样的关键字,只有setjmplongjmp函数,它们的常规用法是先设置信号捕获函数,再调用setjmp,在信号捕获函数中调用longjmp,如果出现异常则会跳到setjmp后面:

#include<setjmp.h>#include<signal.h>#include<stdio.h>jmp_buf buf;voidsig(ints){switch(s){caseSIGSEGV:caseSIGINT:caseSIGFPE:(void)signal(s,sig);longjmp(buf,1);break;default:break;}}intmain(intargc,char*argv[]){(void)signal(SIGINT,sig);(void)signal(SIGFPE,sig);(void)signal(SIGSEGV,sig);if(setjmp(buf)==0){int*p=nullptr;*p=0;}else{printf("exception\n");}

我们可以使用宏来模拟try,catch

#defineTRYif(setjmp(buf)==0){#defineCATCH\}\else

这样就可以写成下面的形式了:

TRY{}CATCH{}

目前这种形式不支持嵌套捕获,比如:

TRY{TRY{}CATCH{}//如果这里出现异常,就不能捕获}CATCH{}

要支持捕获,也很简单,把jmp_buf设置成数组,再使用一个变量来记录深度,使用一次TRY则加1,CATCH时减1即可:

jmp_buf buf[256]={};uint8_tdepth=0;#defineTRYif(setjmp(buf[depth++])==0){#defineCATCH\--depth;\}\elsevoidsig(ints){switch(s){caseSIGSEGV:caseSIGINT:caseSIGFPE:(void)signal(s,sig);longjmp(buf[--depth],1);break;default:break;}}

测试代码:

#include<setjmp.h>#include<signal.h>#include<stdint.h>#include<stdio.h>jmp_buf buf[256]={};uint16_tdepth=0;#defineTRYif(setjmp(buf[depth++])==0){#defineCATCH\--depth;\}\elsevoidsegv(){int*v=nullptr;*v=1;printf("%p\n",v);}voiddiv0(){intv=0;printf("%d\n",1/v);}voidsig(ints){switch(s){caseSIGSEGV:caseSIGINT:caseSIGFPE:(void)signal(s,sig);longjmp(buf[--depth],1);break;default:break;}}voidtest(){TRY{TRY{segv();}CATCH{printf("SIGSEGV exception\n");}div0();}CATCH{printf("SIGFPE exception\n");}}intmain(intargc,char*argv[]){(void)signal(SIGINT,sig);(void)signal(SIGFPE,sig);(void)signal(SIGSEGV,sig);TRY{test();}CATCH{printf("test exception\n");}printf("ok\n");return0;}

如果是使用的VC编译器和调试器,在除0的地方会直接断下来,并不会继续执行,所以触发不了SIGFPE信号,这是由于SEH异常机制导致,如果想要实现与GCC一样的行为,即POSIX行为,则需要拦截SEH,手动触发SIGFPE信号:

#if_MSC_VER#include<windows.h>LONG WINAPIseh_handler(EXCEPTION_POINTERS*e){if(e->ExceptionRecord->ExceptionCode==EXCEPTION_INT_DIVIDE_BY_ZERO){raise(SIGFPE);returnEXCEPTION_CONTINUE_EXECUTION;}returnEXCEPTION_CONTINUE_SEARCH;}#endif

再调用:

#if_MSC_VERAddVectoredExceptionHandler(1,seh_handler);#endif

完整代码:

#include<setjmp.h>#include<signal.h>#include<stdint.h>#include<stdio.h>#if_MSC_VER#include<windows.h>LONG WINAPIseh_handler(EXCEPTION_POINTERS*e){if(e->ExceptionRecord->ExceptionCode==EXCEPTION_INT_DIVIDE_BY_ZERO){raise(SIGFPE);returnEXCEPTION_CONTINUE_EXECUTION;}returnEXCEPTION_CONTINUE_SEARCH;}#endifjmp_buf buf[256]={};uint16_tdepth=0;#defineTRYif(setjmp(buf[depth++])==0){#defineCATCH\--depth;\}\elsevoidsegv(){int*v=0;*v=1;printf("%p\n",v);}voiddiv0(){intv=0;printf("%d\n",1/v);}voidsig(ints){switch(s){caseSIGSEGV:caseSIGINT:caseSIGFPE:(void)signal(s,sig);longjmp(buf[--depth],1);break;default:break;}}voidtest(){TRY{TRY{segv();}CATCH{printf("SIGSEGV exception\n");}div0();}CATCH{printf("SIGFPE exception\n");}}intmain(intargc,char*argv[]){#if_MSC_VERAddVectoredExceptionHandler(1,seh_handler);#endif(void)signal(SIGINT,sig);(void)signal(SIGFPE,sig);(void)signal(SIGSEGV,sig);TRY{TRY{TRY{segv();}CATCH{printf("SIGSEGV exception\n");}div0();}CATCH{printf("SIGFPE exception\n");}test();}CATCH{printf("test exception\n");}printf("ok\n");return0;}

如果对你有帮助,欢迎点赞收藏!

http://www.jsqmd.com/news/322799/

相关文章:

  • Python+django基于微信小程序的天文知识科普系统设计与实现-
  • 脑机接口技术在医疗康复领域的应用与投资
  • Flutter 三端应用实战:OpenHarmony 简易“动态色盘生成器”交互模式深度解析
  • T1飞跃系列(用友畅捷通旗下产品)是面向小微企业的标准化管理软件,与市场上其他主流企业管理软件
  • Python+django基于微信小程序的校园互助论坛学习社区95l77
  • 大数据领域Flink与其他计算框架的对比分析
  • 数字化转型关键一步:商贸物流软件的核心功能与应用场景
  • Python+django基于微信小程序的医院医疗设备报修管理系统设计-
  • 在企业实际运营中,同时集成金蝶和用友两套系统
  • Python+django基于微信小程序的城市公交查询系统 web pc 小程序手机端
  • Word自动编号完美对齐技巧
  • AI元人文:再论真假悟空——从技术迷思到集体反思的文明转向
  • 从遮蔽到表达:当地板行业迎来它的“新质生产力”
  • 工业制造业平台
  • Word题注编号间距调整4种方法
  • Plecs中三相电源参数设计详解
  • Python+django基于微信小程序的个人运动健康饮食指导管理平台的设计与实现-
  • Intersolar Africa 2026将助力内罗毕成为东非地区太阳能与储能产业的关键枢纽
  • Python+django基于微信小程序的书院会议室预约系统的设计与实现-
  • Python+django基于微信小程序的公开课选课打卡管理系统的设计与实现-
  • Chrome/Edge/Firefox如何打开书签栏?
  • Python+django基于微信小程序大数据技术的美食分享系统的设计与实现-爬虫可视化大屏
  • VDURA推出闪存救援计划应对SSD价格飙升挑战全闪存对手
  • 移动开发领域里移动 UI 设计的视觉传达效果
  • 想拿下AI社交,腾讯元宝派不能太“保守”
  • Python+django基于安卓的小餐饮餐桌包厢预订管理系统的设计与实现-小程序
  • reprepro工具.包制作.deb包签名、索引并发布可靠apt源
  • Python+django基于微信的借书驿站图书借阅小程序的设计与实现-
  • CSG宣布与DISH Network续签合同
  • 我的第一篇博客