news 2026/3/31 23:35:57

C语言中嵌套捕获异常

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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;}

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

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

Python+django基于微信小程序的城市公交查询系统 web pc 小程序手机端

文章目录 系统概述技术架构核心功能代码示例&#xff08;Django API&#xff09;部署与优化 系统设计与实现的思路主要技术与实现手段源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; 系统概述 基于PythonDjango框架的城市公交查询系统&a…

作者头像 李华
网站建设 2026/3/25 9:24:05

亲测高中自习室:一流企业级体验复盘分享

亲测高中自习室&#xff1a;一流企业级体验复盘分享在高中学业压力日益增大的背景下&#xff0c;“自习室”早已不再是传统“安静自习”的代名词&#xff0c;而是逐渐演变为一种融合学习、管理、科技与服务的新型教育空间。作为一名长期关注教育科技发展的观察者&#xff0c;我…

作者头像 李华
网站建设 2026/3/25 20:54:19

django+Python微信小程序的食堂预约点餐系统的设计与实现

文章目录摘要系统设计与实现的思路主要技术与实现手段源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;摘要 该系统基于Django框架和Python语言开发&#xff0c;旨在为校园或企业食堂提供一套高效的微信小程序预约点餐解决方案。通过整合微…

作者头像 李华
网站建设 2026/3/28 6:00:08

飞机订票系统(11843)

有需要的同学&#xff0c;源代码和配套文档领取&#xff0c;加文章最下方的名片哦 一、项目演示 项目演示视频 二、资料介绍 完整源代码&#xff08;前后端源代码SQL脚本&#xff09;配套文档&#xff08;LWPPT开题报告&#xff09;远程调试控屏包运行 三、技术介绍 Java…

作者头像 李华
网站建设 2026/3/26 14:39:05

基于python的登录网站验证码的生成与识别系统(源码+文档)

项目简介 登录网站验证码的生成与识别系统实现了以下功能&#xff1a; 用python实现登录网站验证码功能&#xff1a; 设计两种验证码&#xff1a; 1 图形验证码&#xff0c;用python web框架Django能够实现动态刷新。 2 滑动验证码&#xff1a; 1.服务端随机生成小拼块和带有…

作者头像 李华
网站建设 2026/3/14 5:57:36

大数据领域数据预处理的前沿趋势分析

大数据领域数据预处理的前沿趋势分析 关键词:数据预处理、大数据、自动化清洗、实时流处理、隐私增强、AI驱动、图数据处理 摘要:在大数据时代,“数据质量决定决策质量"已成为行业共识。数据预处理作为数据分析的"第一公里”,直接影响后续建模、挖掘的效果。本文…

作者头像 李华