交流
商城
MCN
登入
注册
首页
提问
分享
讨论
建议
公告
动态
发表新帖
发表新帖
c语言第5章:异常处理
分享
未结
0
683
李延
LV6
2022-05-20
悬赏:20积分
# 1 说明 在c语言中,模仿java 写一个通过try-catch 以及 Throw 的一个异常机制。如下: ```c TRY run(); // 执行自己的方法 CATCH(&ex1) printf("发生异常ex1\n"); // 捕获到一个异常 CATCH(&ex2) printf("发生异常ex2\n"); // 捕获到一个异常 FINILLY printf("执行finally\n"); // 执行finilly ENDTRY ``` 同时通过Throw 抛出异常 ```c int run(Exception *exception) { Throw(exception); return 0; } ``` # 2 原理 首先我们所有的try、catch等命令都是通过宏定义进行的. 对于异常的调整通过setjmp.h 的 longjmp和setjmp 函数,实现异常发生时的跳转。 # 3 实现 ## 3.1 except.h ```c #ifndef EXCEPTION #define EXCEPTION #include <setjmp.h> #include <pthread.h> #include "stdlib.h" #include "assert.h" #define EXCEPTION_ERROR 1 //发生异常标记 #define EXCEPTION_OK 0 //未异常标记 pthread_key_t key; /// 异常定义 typedef struct { const char *reason; } Exception; typedef struct Try_module_stack { struct Try_module_stack *tryModuleStack; struct Error_msg *errorMsg; int Exception_type; int finally_type; jmp_buf except_jmpBuf; } Try_module_stack; typedef struct Error_msg { Exception *exception; const char *_File; //异常代码文件行数 unsigned _Line; //异常 行数 } Error_msg; void throwFunction(Exception *exception, const char *_File, unsigned _Line); void printfError(Error_msg *msg); /// 可能抛出异常的代码块 #define TRY \ do {\ int except_type;\ Try_module_stack *tryModuleStack = pthread_getspecific(key);\ Try_module_stack *newTryModuleStack = (Try_module_stack *) malloc(sizeof(Try_module_stack));\ newTryModuleStack->errorMsg = NULL;\ Error_msg msg;\ pthread_setspecific(key, newTryModuleStack);\ if (tryModuleStack != NULL) {\ newTryModuleStack->tryModuleStack = tryModuleStack;\ } else {\ newTryModuleStack->tryModuleStack = NULL;\ }\ except_type = setjmp(newTryModuleStack->except_jmpBuf);\ if (newTryModuleStack->errorMsg != NULL) {\ msg = *newTryModuleStack->errorMsg;\ }\ if (except_type == 0) { #define ENDTRY \ }\ int exception_type = newTryModuleStack->Exception_type;\ Try_module_stack *old = newTryModuleStack->tryModuleStack;\ if (old == NULL) {\ pthread_key_delete(key);\ } else {\ pthread_setspecific(key, old);\ }\ if (newTryModuleStack->errorMsg != NULL) {\ free(newTryModuleStack->errorMsg);\ }\ free(newTryModuleStack);\ if (exception_type == -2) {\ longjmp(tryModuleStack->except_jmpBuf, EXCEPTION_ERROR);\ }else \ if (exception_type == -4) {\ printfError(&msg); \ assert(0);\ } \ } while (0); /// 捕获特定异常 #define CATCH(ex) \ } else if (newTryModuleStack->Exception_type == -1 && newTryModuleStack->errorMsg->exception == &ex1) { #define DEFCATCH \ } else if (newTryModuleStack->Exception_type == -1 ) { #define FINILLY \ }\ if (newTryModuleStack->finally_type != 1) {\ newTryModuleStack->finally_type = 1; /// 抛出异常 #define Throw(exception) throwFunction(exception, __FILE__, __LINE__) #endif /* __EXCEPION_H__ */ ``` ## 3.2 except.c ```c #include "except.h" #include "stdio.h" void throwFunction(Exception *exception, const char *_File, unsigned _Line) { Try_module_stack *tryModuleStack = pthread_getspecific(key); Error_msg *msg = (Error_msg *) malloc(sizeof(Error_msg)); msg->exception = exception; msg->_File = _File; msg->_Line = _Line; if (tryModuleStack != NULL) { if (tryModuleStack->errorMsg != NULL && tryModuleStack->tryModuleStack != NULL) { tryModuleStack->Exception_type = -2; tryModuleStack->tryModuleStack->errorMsg = msg; tryModuleStack->tryModuleStack->Exception_type = -1; } else if (tryModuleStack->tryModuleStack == NULL) { tryModuleStack->Exception_type = -4; tryModuleStack->errorMsg = msg; } else if (tryModuleStack->errorMsg != NULL) { tryModuleStack->Exception_type = -3; tryModuleStack->errorMsg = msg; } else { tryModuleStack->Exception_type = -1; tryModuleStack->errorMsg = msg; } longjmp(tryModuleStack->except_jmpBuf, EXCEPTION_ERROR); } else { printfError(msg); assert(0); } } void printfError(Error_msg *msg) { printf("has error :[%s], at : [%s] in [%d]\n", msg->exception->reason, msg->_File, msg->_Line); } ``` # 4 测试类 ```c #include "../except/except.h" #include "stdio.h" Exception ex1 = {"ex1"}; Exception ex2 = {"ex2"}; Exception ex3 = {"ex3"}; Exception ex4 = {"ex4"}; int run(Exception *exception) { Throw(exception); return 0; } void run2(Exception *exception) { TRY run(exception); CATCH(&ex1) printfError(&msg); Throw(exception); CATCH(&ex2) printfError(&msg); FINILLY printf("执行finally\n"); ENDTRY } void ExceptionTest(Exception *exception) { TRY run2(exception); CATCH(&ex1) printfError(&msg); CATCH(&ex2) printfError(&msg); FINILLY printf("执行finally\n"); Throw(exception); ENDTRY } int main() { ExceptionTest(&ex1); // 异常1 ExceptionTest(&ex2); // 异常2 ExceptionTest(&ex3); // 异常3 ExceptionTest(&ex4); // 异常4 return 0; } ```
回帖
消灭零回复
提交回复
热议榜
java 相关知识分享
8
好的程序员与不好的程序员
6
写给工程师的十条精进原则
5
spring boot以jar包运行配置的logback日志文件没生成
5
一步一步分析SpringBoot启动源码(一)
5
MockMvc测试
5
【吐槽向】是不是有个吐槽的板块比较好玩
4
logstash jdbc同步mysql多表数据到elasticsearch
3
IntelliJ IDEA 优质License Server
3
.gitignore忽略规则
3
SpringBoot启动源码分析
3
一步一步分析SpringBoot启动源码(三)
3
2
一步一步分析SpringBoot启动源码(二)
2
积分不够将无法发表新帖
2
官方产品
Meta-Boot - 基于MCN
MCN - 快速构建SpringBoot应用
微信扫码关注公众号