news 2026/4/4 10:44:03

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/4/1 3:18:26

HOPE架构深度解析:高阶多项式展开与MLP记忆新范式

HOPE架构深度解析: 高阶多项式展开与MLP记忆新范式 ——从Transformer的算力困境到线性架构的范式革命—— 技术专栏博客 2026年1月 目录 目录 第一部分:困境与突围——后Transformer时代的算力战争 1. Transformer架构的物理边界与理论缺陷 1.1 二次复杂度(Quadr…

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

AI应用架构师带你领略AI虚拟娱乐的场景化应用

从0到1构建AI虚拟娱乐帝国:架构师视角的场景化应用拆解 关键词 AI虚拟娱乐、场景化架构、数字人交互、生成式AI、实时渲染、多模态融合、元宇宙娱乐 摘要 当我们谈论AI与娱乐的结合时,你想到的是虚拟偶像的演唱会?还是能自动生成剧情的AI剧本杀?或是能陪你聊天的虚拟游…

作者头像 李华
网站建设 2026/4/3 4:12:13

Anaconda下载及安装保姆级教程(详细图文)

一、先导知识 Anaconda是一款开源的Python和R语言的发行版本&#xff0c;其主要目的是为数据科学、机器学习、大数据处理和科学计算提供一个集成的开发环境。Anaconda集成了大量常用的数据科学库和工具&#xff0c;并附带了强大的环境管理和包管理功能&#xff0c;使得Python环…

作者头像 李华
网站建设 2026/4/3 11:21:51

SQL调优新维度:百万级数据下的性能跃迁实战

SQL调优新维度&#xff1a;百万级数据下的性能跃迁实战 某金融平台因一条未优化的SQL导致实时风控延迟200ms&#xff0c;单日交易损失超百万——这不是电影情节&#xff0c;而是2025年某头部机构的真实事故。本文将通过百万级数据验证的SQL优化方案&#xff0c;从索引策略到执行…

作者头像 李华