commit 9ac75c09aca07c376a1b7570c415e2e6b16f5498 Author: ranchuan Date: Tue Jun 18 19:37:43 2024 +0800 初步实现异常捕获机制 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d163863 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..4eb1651 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,21 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE" + ], + "windowsSdkVersion": "10.0.22621.0", + "compilerPath": "C:/cygwin64/bin/gcc.exe", + "cStandard": "c17", + "cppStandard": "c++17", + "intelliSenseMode": "linux-gcc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..4c9cc3d --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,46 @@ +{ + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "(Windows) 启动", + "type": "cppvsdbg", + "request": "launch", + "program": "${workspaceFolder}/build/hello.exe", + "args": [], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [], + "console": "externalTerminal" + }, + { + "name": "(gdb) 启动", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/hello.exe", + "args": [], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "miDebuggerPath": "/path/to/gdb", + "setupCommands": [ + { + "description": "为 gdb 启用整齐打印", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "将反汇编风格设置为 Intel", + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + } + ] + } + + + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..411469a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "files.associations": { + "stdio.h": "c", + "regex.h": "c", + "test1.h": "c", + "stdint.h": "c", + "exception.h": "c", + "mythread.h": "c" + } +} \ No newline at end of file diff --git a/ReadMe.txt b/ReadMe.txt new file mode 100644 index 0000000..2417e74 --- /dev/null +++ b/ReadMe.txt @@ -0,0 +1,8 @@ + + +2024.6.18 + 初步实现 基于线程的异常捕获,触发异常时可以自动释放异常捕获期间的动态内存 + + + + diff --git a/main.c b/main.c new file mode 100644 index 0000000..023b314 --- /dev/null +++ b/main.c @@ -0,0 +1,78 @@ +#include "stdio.h" +#include "regex.h" +#include "stdlib.h" +#include "stdint.h" +#include "soft/exception.h" +#include "soft/mythread.h" +#include "unistd.h" + + +int thread_fun(void *t){ + printf("run in thread_fun.\n"); + + while(1){ + sleep(5); + throw_("s"); + } + return 0; +} + + + +void SystemInit(); +extern char **environ; +int main(int argc,char *argv[]){ + int id; + printf("hello world.\n"); + + + + // while(p&&(*p)){ + + // printf("%s\n",*p++); + // } + + // printf("a+b=%d",test_add(3,5)); + id=myth_create(thread_fun,NULL); + id=myth_create(NULL,NULL); + // sleep(10); + myth_join(); +} + + + + +#define func_def(...) + + + + +#define SLOT_FUN_RUN(fun,param) \ + ((slot_fun_def)(fun))(param[0],param[1],param[2],\ + param[3],param[4],param[5],param[6],param[7]) + +typedef void (*slot_fun_def)(size_t a,size_t b,size_t c,size_t d,size_t e,size_t f,size_t g,size_t h); + + + +void funptr_test(){ + printf("print from funptr_test fun.\n"); +} + +void add_test(int a,int b,void (*f)()){ + printf("add_fun:%d+%d=%d\n",a,b,a+b); + f(); +} + +void SystemInit() +{ + func_def(int (int a,int b){ + int a; + return; + }); + size_t pars[8]={4,5,(size_t)funptr_test}; + SLOT_FUN_RUN(add_test,pars); +} + + + diff --git a/make.py b/make.py new file mode 100644 index 0000000..69c5108 --- /dev/null +++ b/make.py @@ -0,0 +1,189 @@ + +# -*- coding: gbk -*- + + + + +import os +import sys +import time + + +''' + +޸ıű֮Ҫȫһ + +''' + + +CC = 'gcc' +# CC = 'C:\\ARM_GCC\\bin\\arm-none-eabi-gcc' + +# AS = CC + ' -x assembler-with-cpp' + +# HEX = 'C:\\ARM_GCC\\bin\\arm-none-eabi-objcopy' + ' -O ihex' +# BIN = 'C:\\ARM_GCC\\bin\\arm-none-eabi-objcopy' + ' -O binary -S' + +CSRC = [] + +CINC = ['-Isoft'] + +CDEF = ["-DTEST"] + +ASRC = [] + +BUILD_DIR = 'build' + +TARGET = 'hello' + +# CFLAG = ["-Wall -pedantic -specs=nano.specs -mcpu=cortex-m3 -mthumb -lc -lm -lnosys -Og -Tstm32_boot.ld", +# f"-Wl,-Map={BUILD_DIR}/{TARGET}.map,--cref -Wl,--gc-sections"] +CFLAG = ["-Wall -pedantic -g"] + +# ҵָ׺ļ +def find_type(path:str,fix:list[str]): + dlist=os.listdir(path) + file_list=[] + for i in dlist: + ps=os.path.join(path, i) + if os.path.isdir(ps): + file_list+=find_type(ps,fix) + else: + suf=ps.split('.')[-1] + if(suf in fix): + file_list.append(ps) + return file_list + + + +''' +.cΪ.oļ +űҪʵ .cļ޸ ±Ӧļ.oļ +gcc -c test.c -o test.o + +ϵ.dļ +gcc -MM main.c -o build/main.d + + + + + +''' + + +def tran_path(path:str): + p=path.replace('\\','/') + p=p.replace('/','_') + if(p[0]=='.'): + return p[1:] + else: + return p + + +# жǷҪ +def check_rebuild(dst:str,src:list[str]): + if(not os.path.exists(dst)): + return True + dst_time=os.path.getmtime(dst) + src_time=[] + for i in src: + src_time.append(os.path.getmtime(i)) + src_time.sort() + if(src_time[-1]>dst_time): + return True + return False + + + +# ȡ.dļļб +def read_depend_files(name:str): + with open(name) as f: + t=f.readline() + t=t.split(':')[-1].strip() + t=t.split(' ') + # print(f"б{t}") + return t + + +# ϵ +def build_depend(src:list[str]): + flags=f"{' '.join(CINC)} {' '.join(CDEF)} {' '.join(CFLAG)}" + for i in src: + name=tran_path(i).split('.')[0] + dst='.'.join([name,'d']) + dst=os.path.join(BUILD_DIR,dst) + if(check_rebuild(dst,[i])): + cmd=f"{CC} -MM {i} -o {dst} {flags}" + print(cmd) + ret=os.system(cmd) + if(ret): + exit() + + +# мļ +def build_object(src:list[str]): + flags=f"{' '.join(CINC)} {' '.join(CDEF)} {' '.join(CFLAG)}" + for i in src: + name_l=tran_path(i).split('.') + name=name_l[0] + file_type=name_l[-1] + dst='.'.join([name,'o']) + dst=os.path.join(BUILD_DIR,dst) + cd='.'.join([name,'d']) + cmd = '' + if(file_type in ['c','.C']): + cd=os.path.join(BUILD_DIR,cd) + if(check_rebuild(dst,read_depend_files(cd))): + cmd=f"{CC} -c {i} -o {dst} {flags}" + elif(file_type in ['s','S','asm','ASM']): + if(check_rebuild(dst,[i])): + cmd=f"{AS} -c {i} -o {dst} {flags}" + if(len(cmd)>0): + print(cmd) + ret=os.system(cmd) + if(ret): + exit() + + +# ɿִļ +def build_target(src:list[str]): + flags=f"{' '.join(CINC)} {' '.join(CDEF)} {' '.join(CFLAG)}" + obj_list=[] + for i in src: + name=tran_path(i).split('.')[0] + obj_list.append(BUILD_DIR+'/'+'.'.join([name,'o'])) + dst=os.path.join(BUILD_DIR,TARGET) + if(check_rebuild(dst,obj_list)): + cmd=f"{CC} {' '.join(obj_list)} -o {dst} {flags}" + print(cmd) + ret=os.system(cmd) + if(ret): + exit() + else: + print("£ҪɵĿ") + + +def main(): + global CSRC + global ASRC + CSRC+=find_type('./',['c','C']) + # ASRC+=find_type('./',['s','S','asm','ASM']) + + if(not os.path.exists(BUILD_DIR)): + os.makedirs(BUILD_DIR) + + print("ϵ") + build_depend(CSRC) + print("ɶļ") + build_object(CSRC) + build_object(ASRC) + print("Ŀļ") + build_target(CSRC+ASRC) + # os.system(f"{HEX} {BUILD_DIR}/{TARGET} {BUILD_DIR}/{TARGET}.hex") + # os.system(f"{BIN} {BUILD_DIR}/{TARGET} {BUILD_DIR}/{TARGET}.bin") + +if __name__ == "__main__": + main() + + + diff --git a/soft/exception.c b/soft/exception.c new file mode 100644 index 0000000..c78b7ea --- /dev/null +++ b/soft/exception.c @@ -0,0 +1,97 @@ + + +#include "setjmp.h" +#include "stdio.h" +#include "stdlib.h" +#include "unistd.h" +#include "string.h" +#include "stdarg.h" +#include "exception.h" +#include "mystdlib.h" + + + +exception_def *exception(){ + static exception_def frame={0}; + return &frame; +} + + + + + +void __throw(char *file,int line,const char *fmt,...){ + exception_def *f=exception(); + jmp_fram *h=f->jmp_head; + char *buff=0; + int length=0; + va_list args; + f->file=file; + f->line=line; + buff=f->log; + va_start(args, fmt); + length += vsnprintf(buff + length, THROW_LOG__MAX_SIZE - length - 1, fmt, args); + va_end(args); + longjmp((h->fram),1); +} + + + + +char *err_(){ + exception_def *f=exception(); + return f->log; +} +char *file_(){ + exception_def *f=exception(); + return f->file; +} +int line_(){ + exception_def *f=exception(); + return f->line; +} +void func_two(); + +int test_add(int a, int b) +{ + printf("setjmp test.\n"); + try_{ + printf("first enter setjmp.\n"); + + try_{ + printf("try in try.\n"); + func_two(); + // throw_("throw two err."); + }catch_{ + printf("file=%s,line=%d,err=%s.\n",file_(),line_(),err_()); + } + throw_("throw a err."); + + }catch_{ + printf("sssss\n"); + printf("file=%s,line=%d,err=%s.\n",file_(),line_(),err_()); + try_{ + printf("try in catch.\n"); + func_two(); + // throw_("throw two err."); + }catch_{ + printf("file=%s,line=%d,err=%s.\n",file_(),line_(),err_()); + } + } + printf("setjmp end.\n"); + return 0; +} + + + + + +void func_two(){ + printf("in func:%s\n",__func__); + void *p=mem_malloc(512); + throw_("throw in func_two. in func:%s",__func__); + mem_free(p); +} + + + diff --git a/soft/exception.h b/soft/exception.h new file mode 100644 index 0000000..e4d80c3 --- /dev/null +++ b/soft/exception.h @@ -0,0 +1,104 @@ + + +#ifndef exception_h__ +#define exception_h__ + +#include "setjmp.h" +#include "mystdlib.h" + +#define THROW_LOG__MAX_SIZE 1024 + + +typedef struct _jmp_fram{ + struct _jmp_fram *next; + struct _jmp_fram *last; + map_def *mem; + jmp_buf fram; +}jmp_fram; + + +typedef struct{ + size_t jmp_num; + jmp_fram *jmp_head; + int ret; + char *file; + int line; + char log[THROW_LOG__MAX_SIZE]; +}exception_def; + + + +#define jmp_next(j) {\ + if((*j)){\ + (*j)->next=calloc(sizeof(jmp_fram),1);\ + (*j)->next->last=(*j);\ + (*j)=(*j)->next;\ + }else{\ + (*j)=calloc(sizeof(jmp_fram),1);\ + }\ +} + +#define jmp_last(j) {\ + if((*j)){\ + jmp_fram *l=(*j)->last;\ + if(l){\ + __mem_mov(&(l)->mem,&(*j)->mem);\ + }\ + free(*j);\ + (*j)=l;\ + if(*j){\ + (*j)->next=0;\ + }\ + }\ +} + + +#define jmp_clear(j) {\ + if((*j)){\ + jmp_fram *l=(*j)->last;\ + __mem_clear(&(*j)->mem);\ + free(*j);\ + (*j)=l;\ + if(*j){\ + (*j)->next=0;\ + }\ + }\ +} + + +#define __try(){\ + exception_def *f=exception();\ + jmp_fram **h=&f->jmp_head;\ + int ret;\ + jmp_next(h);\ + ret= setjmp(((*h)->fram));\ + if(ret){\ + jmp_clear(h);\ + }\ + f->ret=ret;\ +} + +#define try_ __try();if(exception()->ret==0){ +#define catch_ {\ + exception_def *f=exception();\ + jmp_fram **h=&f->jmp_head;\ + jmp_last(h);\ +}}else + +#define throw_(fmt,...) __throw(__FILE__,__LINE__,fmt,##__VA_ARGS__) + +exception_def *exception(); +void __throw(char *file,int line,const char *fmt,...); + + + + +int test_add(int a,int b); + + + + + + +#endif + diff --git a/soft/mystdlib.c b/soft/mystdlib.c new file mode 100644 index 0000000..00d687f --- /dev/null +++ b/soft/mystdlib.c @@ -0,0 +1,107 @@ + +#include "mystdlib.h" +#include "string.h" +#include "exception.h" +#include "stdio.h" + + +static void __mem_append_m(map_def **m,void *p); + + +void __mem_clear(map_def **m){ + if(!(*m)){ + return; + } + size_t *map=(*m)->mem_map; + size_t size=(*m)->map_size; + for(size_t i=0;imem_map; + for(size_t i=0;i<(*s)->map_size;i++){ + if(map[i]){ + __mem_append_m(d,(void *)map[i]); + } + } + free(*s); + (*s)=0; + printf("mem mov end.\n"); +} + + + + +void mem_free(void *p){ + exception_def *th=exception(); + map_def **m=&th->jmp_head->mem; + if(*m){ + for(size_t i=0;i<(*m)->map_size;i++){ + if((*m)->mem_map[i]==(size_t)p){ + (*m)->mem_map[i]=0; + printf("free eme_p=%08lx\n",(size_t)p); + (*m)->mam_used--; + break; + } + } + } + free(p); +} + +static void __mem_append_m(map_def **m,void *p){ + if(!(*m)){ + (*m)=calloc(sizeof(map_def)+MAP_SIZE_STEP*sizeof(size_t),1); + (*m)->map_size=MAP_SIZE_STEP; + } + if((*m)->mam_used>=(*m)->map_size){ + map_def *mt=*m; + *m=calloc(sizeof(map_def)+((*m)->map_size+ MAP_SIZE_STEP)*sizeof(size_t),1); + (*m)->mam_used=mt->mam_used; + (*m)->map_size=mt->map_size+MAP_SIZE_STEP; + memcpy((*m)->mem_map,mt->mem_map,mt->map_size*sizeof(size_t)); + free(mt); + } + if((*m)->mam_used<(*m)->map_size){ + for(size_t i=0;i<(*m)->map_size;i++){ + if((*m)->mem_map[i]==0){ + (*m)->mem_map[i]=(size_t)p; + printf("append eme_p=%08lx\n",(size_t)p); + (*m)->mam_used++; + break; + } + } + } +} + +static void __mem_append(void *p){ + exception_def *th=exception(); + map_def **m=&th->jmp_head->mem; + __mem_append_m(m,p); +} + +void *mem_malloc(size_t size){ + void *p=malloc(size); + __mem_append(p); + return p; +} + +void *mem_calloc(size_t memb_size,size_t memb_num){ + void *p=calloc(memb_size,memb_num); + __mem_append(p); + return p; +} + + + diff --git a/soft/mystdlib.h b/soft/mystdlib.h new file mode 100644 index 0000000..92fc475 --- /dev/null +++ b/soft/mystdlib.h @@ -0,0 +1,28 @@ + + +#ifndef mystdlib_h__ +#define mystdlib_h__ + +#include "stdint.h" +#include "stdlib.h" + + +#define MAP_SIZE_STEP 50 + + + +typedef struct _map_def{ + size_t map_size; + size_t mam_used; + size_t mem_map[0]; +}map_def; + + +void __mem_clear(map_def **m); +void __mem_mov(map_def **d,map_def **s); + +void *mem_calloc(size_t memb_size,size_t memb_num); +void *mem_malloc(size_t size); +void mem_free(void *p); + +#endif diff --git a/soft/mythread.c b/soft/mythread.c new file mode 100644 index 0000000..05ab92a --- /dev/null +++ b/soft/mythread.c @@ -0,0 +1,87 @@ + + +#include "pthread.h" +#include "unistd.h" +#include "mythread.h" +#include "exception.h" +#include "stdio.h" + + +typedef struct _myth_def{ + struct _myth_def *next; + struct _myth_def *last; + pthread_t th; + exception_def except; + size_t id; + int (*func)(void *); + void *arg; +}myth_def; + +typedef struct{ + myth_def *head; + +}self_def; +static self_def g_self; + + +int pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine) (void *), void *arg); + + + +static void *p_thread(void *t){ + myth_def *th=(myth_def *)t; + th->id=(size_t)pthread_self(); + printf("func:%08lx start id=%d.\n",(size_t)th->func,th->id); + try_{ + if(!th->func){ + throw_("th->func was null."); + } + th->func(th->arg); + }catch_{ + printf("func:%08lx failed.\n",(size_t)th->func); + printf("file=%s,line=%d,err=%s\n",exception()->file,exception()->line,exception()->log); + } + printf("func:%08lx end.\n",(size_t)th->func); + return 0; +} + + + + +int myth_create(int (*func)(void *t),void *t){ + myth_def *m=calloc(sizeof(myth_def),1); + m->func=func; + m->arg=t; + pthread_create(&m->th,NULL,p_thread,m); + { + self_def *s=&g_self; + if(s->head==NULL){ + s->head=m; + }else{ + myth_def *myth=s->head; + while(myth->next){ + myth=myth->next; + } + myth->next=m; + m->last=myth; + } + } + return m->id; +} + + +int myth_join(){ + self_def *s=&g_self; + myth_def *myth=s->head; + myth_def *old; + while(myth){ + pthread_join(myth->th,NULL); + old=myth; + myth=myth->next; + free(old); + } + s->head=NULL; + return 0; +} + diff --git a/soft/mythread.h b/soft/mythread.h new file mode 100644 index 0000000..337f472 --- /dev/null +++ b/soft/mythread.h @@ -0,0 +1,12 @@ +#ifndef mythread_h__ +#define mythread_h__ + + +#include "pthread.h" + +int myth_create(int (*func)(void *t),void *t); +int myth_join(); + + + +#endif