try、catch、finally、throw的机制实现

1、使用操作系统提供的API来实现。

setjmp、longjmp 这两个函数本身线程安全的

goto 在一个函数栈内跳转,短跳。

longjmp 可以跨越函数的跳转、函数之间的跳转。

//try catch -->setjmp longjmp

#include <stdio.h>
#include <setjmp.h>

jmp_buf env;
int count = 0;

typedef truct _Exception
{
    jmp_buf env;
    int exceptype;
}Exception;

#define try(excep) if ((excep.exceptype = setjmp(excep.env)) == 0)

void sub_func(int idx)//该函数的栈会被覆盖,不会栈溢出
{
    printf("sub_fuc-->idx:%d\n",idx);

    longjmp(env,idx);//跳转到标签位 //throw
}

int main()
{
    int idx = 0;
    count = setjmp(env);//设置标签位,首次返回0,其它次返回longjmp带过来的值
    if (count == 0)//try
    {
        printf("count:%d\n",count);
        sub_func(++idx);
    }
    else if(count == 1)//catch(1)
    {
        printf("count:%d\n",count);
        sub_func(++idx);
    }
    else if(count == 2)//catch(2)
    {
        printf("count:%d\n",count);
        sub_func(++idx);
    }
    else if(count == 3)//catch(3)
    {
        printf("count:%d\n",count);
        sub_func(++idx);
    }
    else
    {
        printf("other count\n");
    }

    {//finally

    }    

    return 0;
}

try --->setjmp

throw -->longjmp

//try catch -->setjmp longjmp

#include <stdio.h>
#include <setjmp.h>

jmp_buf env;
int count = 0;

typedef truct _Exception
{
    jmp_buf env;
    int exceptype;
}Exception;

#define Try(excep)   if ((excep.exceptype = setjmp(excep.env)) == 0)
#define Catch(excep,ExcepType)  else if(excep.exceptype == ExcepType)
#define Throw(excep,ExcepType)  longjmp(excep.env,ExcepType)
#define Finally  

void throw_func(Exception ex, int idx)//该函数的栈会被覆盖,不会栈溢出
{
    printf("throw_func-->idx:%d\n",idx);
    Throw(ex,idx);
}

int main()
{
    int idx = 0;
    Exception ex;

    Try(ex)
    {
        printf("idx:%d\n",idx);
        throw_func(ex,++idx);
    }
    Catch(ex,1)
    {
        printf("count:%d\n",ex.exceptype);
    }
    Catch(ex,2)
    {
        printf("count:%d\n",ex.exceptype);
    }
    Catch(ex,3)
    {
        printf("count:%d\n",ex.exceptype);
    }
    Finally
    {
        printf("Finally\n");
    }
    
    return 0;
}

2、try/catch   嵌套如何解决

和栈先进后出,后进先出概念一样,使用

每一层try都对应一个setjmp,即对应一个jmp_buf

try过程是一个入栈过程,

throw是出栈过程,

try
{
    try
    {
        try
        {}
        catch()
        {}
    }
    catch()
    {
    
    }
}
catch()
{

}

3、抛出异常时,常带有的信息有在哪个文件,行号,函数名。

_FILE_

_LINE_

_func_

4、多线程同时操作,线程安全try/catch如何保证,线程的私有空间

//try catch -->setjmp longjmp

#include <stdio.h>
#include <setjmp.h>

Exception *header;
//pthread_key_t   //线程的私有空间,每个线程都有一份,虽然每个线程内的key名字,但是值不一样
#define ThreadLocalData pthread_key_t
#define ThreadLocalDataSet(key,value) pthread_setspecific((key),(value))
#define ThreadLocalDataGet(key,value) pthread_getspecific((key))
#define ThreadLocalDataCreate(key,value) pthread_createspecific((key),(value))

#define EXCEPTION_MASSAGE_LENGTH 512
ThreadLocalData ExceptionStack;
typedef truct _Exception
{
    jmp_buf env;
    int exceptype;
    struct _Exception *next; //单向链表,头插法,实现栈
    char msg[EXCEPTION_MASSAGE_LENGTH];
}Exception;

enum{
    ExceptionEntered = 0,
    ExceptionThrown,
    ExceptionHandled,
    ExceptionFinalized,

}

#define Try  do{\
    Exception excep;\
    excep->next = ThreadLocalDataGet(ExceptionStack);\ //获取栈顶
    ThreadLocalDataSet(ExceptionStack, &excep);\ //设置新节点为栈顶

    int Exception_flag = setjmp(excep.env);
    if (Exception_flag == ExceptionEntered){

#define Catch 

#define Finally

void ExceptionThrow(Exception , const char *func, const char *file, int line, 
                    const char *cause, ...)
{
    Exception excep = ThreadLocalDataGet(ExceptionStack);
    ThreadLocalDataSet(ExceptionStack, excep->next);//出栈

    if (excep)
    {
        va_list ap;
        va_start(ap, cause);
        vsprintf(excep.msg, EXCEPTION_MASSAGE_LENGTH,cause,ap);
        va_end(ap);
        longjmp(excep.env,ExceptionThrown);
    }


}


void throw_func(Exception ex, int idx)//该函数的栈会被覆盖,不会栈溢出
{
    printf("throw_func-->idx:%d\n",idx);
    ExceptionThrow( );
}

int main()
{
    int idx = 0;
    Exception ex;

    Try
    {
        printf("idx:%d\n",idx);
        throw_func(ex,++idx);
    }
    Catch
    {
        printf("count:%d\n",ex.exceptype);
    }
    Catch
    {
        printf("count:%d\n",ex.exceptype);
    }
    Catch
    {
        printf("count:%d\n",ex.exceptype);
    }
    Finally
    {
        printf("Finally\n");
    }
    
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值