在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

基于rt_thread實現c語言的try catch finally捕獲崩潰錯誤代碼

冬至子 ? 來源:kangchaoyang003 ? 作者:kangchaoyang003 ? 2023-09-27 11:47 ? 次閱讀

功能:給c語言添加try catch finally語句捕獲崩潰代碼塊,
支持捕捉空指針訪問,未對齊操作,除零崩潰,等等錯誤,幫助你高效調試代碼.
直接上代碼
.h文件內容
#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文件內容

#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:%drn",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:%drn",stack_node->name,stack_node->tid);
#endif
} else {
TLS_FREE(stack_node);
#if ENABLE_DEBUG == 1
LOGI("新建TLS node失敗,self_tid is NULLrn");
#endif
}
} else {
#if ENABLE_DEBUG == 1
LOGI("新建TLS node失敗,malloc failrn");
#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:%drn",stack_node->name,stack_node->tid);
LOGI("TLS node num:%drn",_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:rn");
_print_env_(((char *)&(jb_node->env)),sizeof(jmp_buf));
#endif
return 1;
} else {
#if ENABLE_DEBUG == 1
LOGI("壓棧 jb node失敗,malloc failrn");
#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:rn");
_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 failrn");
#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:rn");
_print_env_(((char *)&(jb_node->env)),sizeof(jmp_buf));
#endif
}
} else {
#if ENABLE_DEBUG == 1
LOGI("查看 jb node env failrn");
#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:%drn",_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 LOGI("%X",env[idx]);
}
LOGI("rn");
}
}
#endif
/*
功能:給c語言添加try catch finally語句捕獲崩潰代碼塊,
支持捕捉空指針訪問,未對齊操作,除零崩潰,等等錯誤,幫助你高效調試代碼
author: VX:kangchaoyang003
*/
移植方法
/*
把 void _exception_catch_(void) 方法放到 cpuport.c文件里面的
void rt_hw_hard_fault_exception(struct exception_info * exception_info)方法最后的
while(1){}之前。如下代碼:
*/
/*

fault exception handler
/
void rt_hw_hard_fault_exception(struct exception_info * exception_info)
{
extern void exception_catch (void);
extern long list_thread(void);
struct stack_frame
context = &exception_info->stack_frame;
if (rt_exception_hook != RT_NULL)
{
rt_err_t result;
result = rt_exception_hook(exception_info);
if (result == RT_EOK)
return;
}
rt_kprintf("psr: 0x%08xn", context->exception_stack_frame.psr);
rt_kprintf("r00: 0x%08xn", context->exception_stack_frame.r0);
rt_kprintf("r01: 0x%08xn", context->exception_stack_frame.r1);
rt_kprintf("r02: 0x%08xn", context->exception_stack_frame.r2);
rt_kprintf("r03: 0x%08xn", context->exception_stack_frame.r3);
rt_kprintf("r04: 0x%08xn", context->r4);
rt_kprintf("r05: 0x%08xn", context->r5);
rt_kprintf("r06: 0x%08xn", context->r6);
rt_kprintf("r07: 0x%08xn", context->r7);
rt_kprintf("r08: 0x%08xn", context->r8);
rt_kprintf("r09: 0x%08xn", context->r9);
rt_kprintf("r10: 0x%08xn", context->r10);
rt_kprintf("r11: 0x%08xn", context->r11);
rt_kprintf("r12: 0x%08xn", context->exception_stack_frame.r12);
rt_kprintf(" lr: 0x%08xn", context->exception_stack_frame.lr);
rt_kprintf(" pc: 0x%08xn", context->exception_stack_frame.pc);
if(exception_info->exc_return & (1 << 2) )
{
rt_kprintf("hard fault on thread: %srnrn", rt_thread_self()->name);
#ifdef RT_USING_FINSH
list_thread();
#endif /* RT_USING_FINSH /
}
else
{
rt_kprintf("hard fault on handlerrnrn");
}
#ifdef RT_USING_FINSH
hard_fault_track();
#endif /
RT_USING_FINSH */
exception_catch ();
while (1);
}
測試代碼
//測試空指針訪問崩潰捕捉,支持無限制嵌套
void test_null_p(void) {
try {
rt_kprintf("try 1rn");
try {
rt_kprintf("try 2rn");
try {
int *p = RT_NULL;
rt_kprintf("try 3rn");
*p = 100;
}
catch {
rt_kprintf("catch 3rn");
rt_kprintf("catch hard fault on thread: %srnrn", rt_thread_self()->name);
try {
rt_kprintf("try 4rn");
}
catch {
rt_kprintf("catch 4rn");
}
finally {
rt_kprintf("finally 4rn");
}
}
finally {
rt_kprintf("finally 3rn");
}
}
catch {
rt_kprintf("catch 2rn");
}
finally {
rt_kprintf("finally 2rn");
}
}
catch {
rt_kprintf("catch 1rn");
}
finally {
rt_kprintf("finally 1rn");
}
while(1) {
}
}
該測試方法放到任意一個線程里面執行:
如下代碼:

/*

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_ONrn");
LED1_OFF;
rt_thread_delay(500); /
延時500個tick */
rt_kprintf("led1_thread running,LED1_OFFrn");
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

*/

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • C語言
    +關注

    關注

    180

    文章

    7605

    瀏覽量

    137020
  • RT-Thread
    +關注

    關注

    31

    文章

    1293

    瀏覽量

    40202
  • printf函數
    +關注

    關注

    0

    文章

    31

    瀏覽量

    5899
收藏 人收藏

    評論

    相關推薦

    Java捕獲異常處理的常用方法

    IllegalArgumentException 類,IllegalStateException 類。捕獲異常的方法使用 trycatch 關鍵字可以捕獲異常,
    發表于 11-27 11:40

    rt_thread(3.0.3)的移植準備工作

    文件夾內容簡介添加RT_Thread源碼到工程組文件夾config.h文件修改board.c文件修改修改main.c函數注意,此時編譯還會存在問題,需要將stm32F10x_it.c
    發表于 08-03 07:44

    Sqlserver Try CatchCatch捕獲錯誤重試一次的方法分享

    使用while重試一次不太好,如果try catch在游標里面,這樣的話每個游標記錄都要在try里面執行兩次。還是需要等到Catch的結果來重試比較合適,所有用IF比較合適改成以下
    發表于 11-10 17:44

    MSN錯誤代碼大全

    MSN錯誤代碼大全  80004005   這是一個泛泛的錯誤代碼,它意味著,“我知道出錯了,但我不知道錯誤是什么”。   第一步,我們可以試著重新注冊MSN所需的dll
    發表于 07-20 22:50 ?2878次閱讀

    2013LabVIEW錯誤代碼

    2013LabVIEW錯誤代碼介紹,通過查看錯誤代碼可知錯誤原因。
    發表于 02-25 15:00 ?9次下載

    Java異常處理之trycatchfinally,throw,throws

    ,程序繼續運行。 java的異常處理是通過5個關鍵字來實現的:trycatchfinally、throw、throws。 二:java異常類的層次結構 三。常見的異常類型 Exce
    發表于 09-27 11:17 ?0次下載
    Java異常處理之<b class='flag-5'>try</b>,<b class='flag-5'>catch</b>,<b class='flag-5'>finally</b>,throw,throws

    基于正點原子精英版stm32f103zet6進行rt_thread(3.0.3)的移植

    文件夾內容簡介添加RT_Thread源碼到工程組文件夾config.h文件修改board.c文件修改修改main.c函數注意,此時編譯還會存在問題,需要將stm32F10x_it.c
    發表于 12-05 11:21 ?0次下載
    基于正點原子精英版stm32f103zet6進行<b class='flag-5'>rt_thread</b>(3.0.3)的移植

    RTthread線程調度詳解

    rt_schedule(void){ struct rt_thread *to_thread; struct rt_thread *from_th
    的頭像 發表于 05-19 17:07 ?2563次閱讀

    N32G432系列通用MCU RT_Thread設備注冊應用筆記

    N32G432系列通用MCU RT_Thread設備注冊應用筆記
    發表于 11-10 19:51 ?3次下載
    N32G432系列通用MCU <b class='flag-5'>RT_Thread</b>設備注冊應用筆記

    N32L43x系列通用MCU RT_Thread設備注冊應用筆記

    N32L43x系列通用MCU RT_Thread設備注冊應用筆記
    發表于 11-10 19:51 ?0次下載
    N32L43x系列通用MCU <b class='flag-5'>RT_Thread</b>設備注冊應用筆記

    N32G4FR系列通用MCU RT_Thread使用指南

    N32G4FR系列通用MCU RT_Thread使用指南
    發表于 11-11 21:50 ?2次下載
    N32G4FR系列通用MCU <b class='flag-5'>RT_Thread</b>使用指南

    N32G455系列通用MCU RT_Thread使用指南

    N32G455系列通用MCU RT_Thread使用指南
    發表于 11-11 21:50 ?2次下載
    N32G455系列通用MCU <b class='flag-5'>RT_Thread</b>使用指南

    公司這套架構統一處理try...catch真香!

    軟件開發springboot項目過程中,不可避免的需要處理各種異常,spring mvc 架構中各層會出現大量的try {...} catch {...} finally {...} 代碼
    的頭像 發表于 02-27 10:47 ?488次閱讀

    使用try-catch捕獲異常會影響性能嗎?

    “BB 不如 show code,看到沒, 老王,我把 try-catch 從 for 循環里面提出來跟在for循環里面做個對比跑一下,你猜猜兩個差多少?”
    的頭像 發表于 04-01 11:08 ?1226次閱讀

    介紹C語言錯誤處理和異常處理的一些常用的方法和策略

    C語言是一種低級的、靜態的、結構化的編程語言,它沒有提供像C++或Java等高級語言中的異常處理機制,例如
    的頭像 發表于 02-28 14:25 ?639次閱讀
    主站蜘蛛池模板: caoporn97人人做人人爱最新| 美女视频一区二区三区在线| 久久亚洲国产成人影院| 天堂网资源www| 亚洲男人天堂网址| 又粗又大的机巴好爽欧美| 亚洲天堂第一页| 韩漫免费网站无遮挡羞羞漫画| 美女黄网站人色视频免费国产| 精品精品国产自在久久高清| 中文天堂在线观看| 亚洲成在人线久久综合| 色伊人网| 欧美+日本+国产+在线观看| 久久婷婷激情综合色综合也去| 国产午夜大片| 五月天天爱| 国产免费一级在线观看| avbobo在线| 伊人欧美在线| 日本黄色免费在线观看| 国产一区二区三区乱码| 在线观看免费视频| 九九久久九九久久| 91成人免费视频| 在线天堂bt种子| 91大神网址| 黄视频免费观看| 四虎三级| 黄色大全片| 天天天射| 欧美网站在线| 亚洲香蕉视频| 毛片网站网址| 天天做夜夜操| 男人操女人视频免费| 在线电影天堂| 猫色网站| 手机看片1024久久| 一区二区三区高清在线| 四虎最新地址|