Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT_thread
Cpp异常Exception
C语言
基于rt_thread实现c语言版本的try catch finally语法,捕获崩溃错误代码
发布于 2023-04-10 00:31:38 浏览:779
订阅该版
[tocm] # 基于rt_thread实现c语言版本的try catch finally语法,捕获崩溃错误代码 ## 功能:给c语言添加try catch finally语句捕获崩溃代码块, ## 支持捕捉空指针访问,未对齐操作,除零崩溃,等等错误,帮助你高效调试代码. ### 直接上代码 .h文件内容 ```c /*功能:给c语言添加try catch finally语句捕获崩溃代码块,支持捕捉空指针访问,未对齐操作,除零崩溃,等等错误,帮助你高效调试代码author: VX:kangchaoyang003*/ #ifndef _C_TRY_CATCH_H_ #define _C_TRY_CATCH_H_ #include "setjmp.h" extern void _exception_catch_(void); extern int _push_(jmp_buf env); extern void _finally_syntax_(void); extern jmp_buf env; #define __try__ if(0==setjmp(env) && _push_(env)) #define __catch__ else #define __finally__ {_finally_syntax_();} #endif ``` .c文件内容 ```c #include "c_try_catch.h" #include "rtdef.h" #include "rtservice.h" #include "setjmp.h" #include "rtthread.h" #define ENABLE_DEBUG 1 #define TLS_MALLOC rt_malloc #define TLS_FREE rt_free #define TLS_MEMCPY rt_memcpy #define TLS_MEMSET rt_memset #define TLS_NULL RT_NULL #define CATCH_CODE (!0) #define LOGI rt_kprintf struct _slist_node { struct _slist_node *next; } ; typedef struct _slist_node _slist_t; struct _try_catch_stack_node { _slist_t list; _slist_t stack; rt_thread_t tid; #if ENABLE_DEBUG == 1 char name[RT_NAME_MAX]; #endif } ; typedef struct _try_catch_stack_node try_catch_stack_node_t; struct _jmp_buf_node { _slist_t list; jmp_buf env; } ; typedef struct _jmp_buf_node jmp_buf_node_t; static _slist_t thread_list; jmp_buf env; static int _list_len_(const _slist_t *l); #if ENABLE_DEBUG == 1 static void _print_env_(char *env,uint32_t len) ; #endif static void _tls_context_read_(void **context) { try_catch_stack_node_t *stack_node = TLS_NULL; _slist_t *pthread_list = &thread_list; rt_thread_t self_tid = rt_thread_self(); const _slist_t *list_node = pthread_list->next; while (list_node != TLS_NULL) { stack_node = (try_catch_stack_node_t *)list_node; if(stack_node!=TLS_NULL&&self_tid!=TLS_NULL&&stack_node ->tid == self_tid) { *context = &(stack_node->stack); #if ENABLE_DEBUG == 1 LOGI("找到已存在的TLS node,thread name:%s,thread tid:%d\r\n",stack_node->name,stack_node->tid); #endif return; } list_node = list_node->next; } stack_node = (try_catch_stack_node_t *)TLS_MALLOC(sizeof(try_catch_stack_node_t)); if(stack_node!=TLS_NULL) { if(self_tid!=TLS_NULL) { TLS_MEMSET(stack_node,0,sizeof(try_catch_stack_node_t)); #if ENABLE_DEBUG == 1 TLS_MEMCPY(stack_node->name,self_tid->name,RT_NAME_MAX); #endif stack_node->tid = self_tid; ((_slist_t *)stack_node)->next = pthread_list->next; pthread_list->next = (_slist_t *)stack_node; *context = &(stack_node->stack); #if ENABLE_DEBUG == 1 LOGI("新建TLS node,thread name:%s,thread tid:%d\r\n",stack_node->name,stack_node->tid); #endif } else { TLS_FREE(stack_node); #if ENABLE_DEBUG == 1 LOGI("新建TLS node失败,self_tid is NULL\r\n"); #endif } } else { #if ENABLE_DEBUG == 1 LOGI("新建TLS node失败,malloc fail\r\n"); #endif } } static void _tls_context_destroy_(void) { try_catch_stack_node_t *stack_node = TLS_NULL; _slist_t *pthread_list = &thread_list; rt_thread_t self_tid = rt_thread_self(); //查找当前线程tls表头 const _slist_t *list_node = pthread_list->next; while (list_node != TLS_NULL) { stack_node = (try_catch_stack_node_t *)list_node; if(stack_node!=TLS_NULL&&self_tid!=TLS_NULL&&stack_node ->tid == self_tid) { if(stack_node->stack.next==TLS_NULL) { /* remove slist head */ _slist_t *node = pthread_list; while (node->next && node->next != &(stack_node->list)) node = node->next; /* remove node */ if (node->next != (_slist_t *)0) node->next = node->next->next; #if ENABLE_DEBUG == 1 LOGI("移除TLS node,thread name:%s,thread tid:%d\r\n",stack_node->name,stack_node->tid); LOGI("TLS node num:%d\r\n",_list_len_(pthread_list)); #endif TLS_FREE(stack_node); } return; } list_node = list_node->next; } } int _push_(jmp_buf env) { jmp_buf_node_t *jb_node = TLS_NULL; _slist_t *context = TLS_NULL; _tls_context_read_((void *)&context) ; if(context!=TLS_NULL) { jb_node = (jmp_buf_node_t *)TLS_MALLOC(sizeof(jmp_buf_node_t)); if(jb_node!=TLS_NULL) { TLS_MEMCPY(jb_node->env,env,sizeof(jmp_buf)); ((_slist_t *)jb_node)->next = context->next; context->next = (_slist_t *)jb_node; #if ENABLE_DEBUG == 1 LOGI("压栈 jb node env:\r\n"); _print_env_(((char *)&(jb_node->env)),sizeof(jmp_buf)); #endif return 1; } else { #if ENABLE_DEBUG == 1 LOGI("压栈 jb node失败,malloc fail\r\n"); #endif } } return 0; } static void _pop_(void) { _slist_t *context = TLS_NULL; _tls_context_read_((void *)&context) ; if(context!=TLS_NULL && context->next!=TLS_NULL) { _slist_t *removed_node = context->next; context->next = context->next->next; if(removed_node!=TLS_NULL) { #if ENABLE_DEBUG == 1 LOGI("出栈 jb node env:\r\n"); _print_env_(((char *)&(((jmp_buf_node_t*)removed_node)->env)),sizeof(jmp_buf)); #endif TLS_FREE(removed_node); } } else { #if ENABLE_DEBUG == 1 LOGI("出栈 jb node env fail\r\n"); #endif } } static void _peek_(jmp_buf *env) { jmp_buf_node_t *jb_node = TLS_NULL; _slist_t *context = TLS_NULL; _tls_context_read_((void *)&context) ; if(context!=TLS_NULL&&env!=TLS_NULL&&context->next!=TLS_NULL) { jb_node=(jmp_buf_node_t *)(context->next); if(jb_node!=TLS_NULL) { TLS_MEMCPY(env,jb_node->env,sizeof(jmp_buf)); #if ENABLE_DEBUG == 1 LOGI("查看 jb node env:\r\n"); _print_env_(((char *)&(jb_node->env)),sizeof(jmp_buf)); #endif } } else { #if ENABLE_DEBUG == 1 LOGI("查看 jb node env fail\r\n"); #endif } } static uint32_t _depth_(void) { uint32_t _depth = 0; _slist_t *context = TLS_NULL; _tls_context_read_((void *)&context) ; _depth = _list_len_(context); #if ENABLE_DEBUG == 1 LOGI("stack depth:%d\r\n",_depth); #endif return _depth; } void _exception_catch_(void) { _peek_(&env); longjmp(env,CATCH_CODE); } void _finally_syntax_(void) { int stack_depth = _depth_(); if(stack_depth>=1) { _pop_(); if(stack_depth==1) { _tls_context_destroy_(); } } } static int _list_len_(const _slist_t *l) { unsigned int len = 0; if(l) { const _slist_t *list = l->next; while (list != RT_NULL) { list = list->next; len ++; } } return len; } #if ENABLE_DEBUG == 1 static void _print_env_(char *env,uint32_t len) { int idx=0; if(env) { for (idx=0;idx
stack_frame; if (rt_exception_hook != RT_NULL) { rt_err_t result; result = rt_exception_hook(exception_info); if (result == RT_EOK){ _exception_catch_(); return; } } rt_kprintf("psr: 0x%08x\n", context->exception_stack_frame.psr); rt_kprintf("r00: 0x%08x\n", context->exception_stack_frame.r0); rt_kprintf("r01: 0x%08x\n", context->exception_stack_frame.r1); rt_kprintf("r02: 0x%08x\n", context->exception_stack_frame.r2); rt_kprintf("r03: 0x%08x\n", context->exception_stack_frame.r3); rt_kprintf("r04: 0x%08x\n", context->r4); rt_kprintf("r05: 0x%08x\n", context->r5); rt_kprintf("r06: 0x%08x\n", context->r6); rt_kprintf("r07: 0x%08x\n", context->r7); rt_kprintf("r08: 0x%08x\n", context->r8); rt_kprintf("r09: 0x%08x\n", context->r9); rt_kprintf("r10: 0x%08x\n", context->r10); rt_kprintf("r11: 0x%08x\n", context->r11); rt_kprintf("r12: 0x%08x\n", context->exception_stack_frame.r12); rt_kprintf(" lr: 0x%08x\n", context->exception_stack_frame.lr); rt_kprintf(" pc: 0x%08x\n", context->exception_stack_frame.pc); if(exception_info->exc_return & (1 << 2) ) { rt_kprintf("hard fault on thread: %s\r\n\r\n", rt_thread_self()->name); #ifdef RT_USING_FINSH list_thread(); #endif /* RT_USING_FINSH */ } else { rt_kprintf("hard fault on handler\r\n\r\n"); } #ifdef RT_USING_FINSH hard_fault_track(); #endif /* RT_USING_FINSH */ _exception_catch_(); while (1); } ``` ## 测试代码 ```c //测试空指针访问崩溃捕捉,支持无限制嵌套 void test_null_p(void) { __try__ { rt_kprintf("__try__ 1\r\n"); __try__ { rt_kprintf("__try__ 2\r\n"); __try__ { int *p = (int*)0x1234aced;//非法地址 rt_kprintf("__try__ 3\r\n"); *p = 100; } __catch__ { rt_kprintf("catch 3\r\n"); rt_kprintf("catch hard fault on thread: %s\r\n\r\n", rt_thread_self()->name); __try__ { rt_kprintf("__try__ 4\r\n"); } __catch__ { rt_kprintf("catch 4\r\n"); } __finally__ { rt_kprintf("finally 4\r\n"); } } __finally__ { rt_kprintf("finally 3\r\n"); } } __catch__ { rt_kprintf("catch 2\r\n"); } __finally__ { rt_kprintf("finally 2\r\n"); } } __catch__ { rt_kprintf("catch 1\r\n"); } __finally__ { rt_kprintf("finally 1\r\n"); } while(1) { } } ``` 该测试方法放到任意一个线程里面执行: 如下代码: ```c /* ************************************************************************* * main 函数 ************************************************************************* */ /** * @brief 主函数 * @param 无 * @retval 无 */ int main(void) { /* * 开发板硬件初始化,RTT系统初始化已经在main函数之前完成, * 即在component.c文件中的rtthread_startup()函数中完成了。 * 所以在main函数中,只需要创建线程和启动线程即可。 */ LED_GPIO_Config(); USART_Config(); led1_thread = /* 线程控制块指针 */ rt_thread_create( "led1", /* 线程名字 */ led1_thread_entry, /* 线程入口函数 */ RT_NULL, /* 线程入口函数参数 */ 512, /* 线程栈大小 */ 3, /* 线程的优先级 */ 20); /* 线程时间片 */ /* 启动线程,开启调度 */ if (led1_thread != RT_NULL) rt_thread_startup(led1_thread); else return -1; } /* ************************************************************************* * 线程定义 ************************************************************************* */ static void led1_thread_entry(void* parameter) { while (1) { LED1_ON; rt_thread_delay(500); /* 延时500个tick */ rt_kprintf("led1_thread running,LED1_ON\r\n"); LED1_OFF; rt_thread_delay(500); /* 延时500个tick */ rt_kprintf("led1_thread running,LED1_OFF\r\n"); test_null_p() ; } } ``` 可以看到如下错误捕捉日志: ``` /* LOG: 新建TLS node,thread name:led1,thread tid:536871776 压栈 jb node env: EFBEADDEEFBEADDEEFBEADDEEFBEADDE7FC080100F4100EFBEADDEEFBEADDEE05020481302000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 __try__ 1 找到已存在的TLS node,thread name:led1,thread tid:536871776 压栈 jb node env: EFBEADDEEFBEADDEEFBEADDEEFBEADDE99C080100F4100EFBEADDEEFBEADDEE05020481302000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 __try__ 2 找到已存在的TLS node,thread name:led1,thread tid:536871776 压栈 jb node env: EFBEADDEEFBEADDEEFBEADDEEFBEADDEB3C080100F4100EFBEADDEEFBEADDEE05020481302000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 __try__ 3 psr: 0x01000000 r00: 0x20001bc0 r01: 0x10000000 r02: 0xf0000000 r03: 0x00000004 r04: 0x00000000 r05: 0x000001f4 r06: 0xdeadbeef r07: 0xdeadbeef r08: 0xdeadbeef r09: 0xdeadbeef r10: 0xdeadbeef r11: 0xdeadbeef r12: 0x00000ff4 lr: 0x08001239 pc: 0x08002e30 hard fault on thread: led1 找到已存在的TLS node,thread name:led1,thread tid:536871776 查看 jb node env: EFBEADDEEFBEADDEEFBEADDEEFBEADDEB3C080100F4100EFBEADDEEFBEADDEE05020481302000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 catch 3 catch hard fault on thread: led1 找到已存在的TLS node,thread name:led1,thread tid:536871776 压栈 jb node env: EFBEADDEEFBEADDEEFBEADDEEFBEADDEE3C080100F4100EFBEADDEEFBEADDEE05020481302000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 __try__ 4 找到已存在的TLS node,thread name:led1,thread tid:536871776 stack depth:4 找到已存在的TLS node,thread name:led1,thread tid:536871776 出栈 jb node env: EFBEADDEEFBEADDEEFBEADDEEFBEADDEE3C080100F4100EFBEADDEEFBEADDEE05020481302000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 finally 4 找到已存在的TLS node,thread name:led1,thread tid:536871776 stack depth:3 找到已存在的TLS node,thread name:led1,thread tid:536871776 出栈 jb node env: EFBEADDEEFBEADDEEFBEADDEEFBEADDEB3C080100F4100EFBEADDEEFBEADDEE05020481302000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 finally 3 找到已存在的TLS node,thread name:led1,thread tid:536871776 stack depth:2 找到已存在的TLS node,thread name:led1,thread tid:536871776 出栈 jb node env: EFBEADDEEFBEADDEEFBEADDEEFBEADDE99C080100F4100EFBEADDEEFBEADDEE05020481302000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 finally 2 找到已存在的TLS node,thread name:led1,thread tid:536871776 stack depth:1 找到已存在的TLS node,thread name:led1,thread tid:536871776 出栈 jb node env: EFBEADDEEFBEADDEEFBEADDEEFBEADDE7FC080100F4100EFBEADDEEFBEADDEE05020481302000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 移除TLS node,thread name:led1,thread tid:536871776 TLS node num:0 finally 1 */ ```
5
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
kangchaoyang003
这家伙很懒,什么也没写!
文章
1
回答
2
被采纳
0
关注TA
发私信
相关文章
1
RT-Thread内存和字符串相关函数与C语言自带的内存和字符串相关函数冲突问题
2
嵌入式RT-thread中初始化线程函数中(void *)entry的意义何在
3
cJSON parse 失败,请问怎么解决?
4
请教一个C语言顺序表的问题,不知道有没有大佬帮吗解答
5
小白请教,关于头文件引用,、、哪些场景需要引用它们?
6
使用中断有warn。。。。。。。。。。。
7
局部变量位置被编译器改写
8
RTthread 两个例程结合在一起会出现incompatible type for argument 2 of 'led_matrix_set_color'
9
有没有在单片机编程使用goto语句的?
10
请问如何读取另一个c文件中的温湿度数据啊
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
805
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部