设为首页 加入收藏

TOP

用c语言模拟c++的异常处理机制(一)
2012-11-01 09:13:51 来源: 作者: 【 】 浏览:888
Tags:语言 模拟 异常 处理 机制
    起因:在c语言工程代码当中,常常要处理各种关于异常的处理,每次当程序比较复杂的时候,就必须用好几个if来嵌套使用,比如
   
    if (xxx)
   
    {
   
    if(xxx)
   
    {
   
    }
   
    else
   
    {
   
    return ERR_NO;
   
    }
   
    }
   
    这样的代码显得非常混乱,也不容易管理,我一直在寻找能跟c++异常机制类似的功能,如果有这样的功能,那么c语言的异常处理不是也很容易打理了么?
   
    由于c的工程当中一般错误都有专有的错误列表,所以在这边,在我们的机制里我只添加了关于错误Id的异常捕捉处理。
   
    思路:
   
    首先,我使用了#define来将c当中没有的关键词替代,比如try,catch,throw,先想到的是用return,break之类的c语言当中先有的关键词来模拟,这就有了我的第一个版本:
   
    #ifndef EXCEPTION_H
   
    #define EXCEPTION_H
   
    // 一个不成熟的exception机制
   
    typedef unsigned int    ERR_TYPE;
   
    #define NO_ERR 0
   
    static ERR_TYPE err; //try-catch-throw错误处理机制
   
    #define try do
   
    #define catch(N) while(0);if(N>=NO_ERR)
   
    #define throw(N) err=N;break;
   
    #define throwAgain(N) err=N;return;
   
    #endif
   
    调用实例代码:
   
    void f(void)
   
    {
   
    try
   
    {
   
    throw(6);
   
    }
   
    catch(err)
   
    {
   
    throwAgain(err);
   
    }
   
    }
   
    int main()
   
    {
   
    try
   
    {
   
    f();
   
    }
   
    catch(err)
   
    {
   
    printf(“%d”, err);
   
    }
   
    }
   
    这个设计的程序有一个很大的问题,那就是它只能在同级的函数下使用try.
   
    这是什么意思呢?如果我需要这样使用:
   
    Int main()
   
    {
   
    Try
   
    {
   
    f();
   
    }
   
    catch(err)
   
    {
   
    printf(“%d”, err);
   
    }
   
    }
   
    Void f()
   
    {
   
    G();
   
    // some codes follows
   
    }
   
    Void g()
   
    {
   
    Throw(3);
   
    }
   
    在g()throw出异常3的时候,main函数没有办法直接捕捉,而是必须在f()函数下面继续执行后面的语句。就是这套设计的机制多个嵌套的函数是没有办法实施的。
   
    那么还有什么办法可以解决这个问题呢?Goto可以吗?不可以,goto也只能在同级的函数下使用。goto是本地的:它只能跳到所在函数内部的标号上,而不能将控制权转移到所在程序的任意地点 .
   
    最后找到一个方法:
   
    #include <setjmp.h>
   
    int setjmp(jmp_buf env)
   
    Returns: 0 if called directly, nonzero if returning from a call to longjmp.
   
    void longjmp(jmp_buf env, int val);
   
    setjmp 和longjmp这2个函数可以在不同的函数进行跳转,只要设置他们的上下文,在用longjmp跳转到这设置好的上下文当中就可以了!!
   
    这2个函数的使用方法:
   
    #include<stdio.h>
   
    #include<setjmp.h>
   
    jmp_buf ebuf;
   
    void f2(void);
   
    int main(void)
   
    {
   
    int i;
   
    printf(“1”);
   
    i=setjmp(ebuf);
   
    if(i==0)
   
    {
   
    f2();
   
    printf(“This will not be printed.”);
   
    }
   
    printf(“%d”,i);
   
    return 0;
   
    }
   
    void f2(void)
   
    {
   
    printf(“2”);
   
    longjmp(ebuf,3);
   
    }
   
    首先,在函数a里面setjmp,将当前函数的env都存储起来,然后在函数b里面调用longjmp,这样就会直接跳转到函数a的setjmp这个地方,longjmp的第二个值作用是在第二次返回a函数的时候setjmp会返回longjmp的第二个参数。
   
    有了这个方法,我们的程序就好设计多了,由于设计多个函数的调用,所以设计的时候使用了链表来处理保存每个函数的env.
   
    全部实现代码如下:
   
    #ifndef LIST_H
   
    #define LIST_H
   
    typedef struct list_head_tag
   
    {
   
    struct list_head_tag *prev;
   
    struct list_head_tag *next;
   
    }list_head;
   
    #define list_for_each(pos, head) \
   
    for ( pos = (head)->next; \
   
    pos != (head); \
   
    pos = pos->next)
   
    #define list_for_each_safe(pos,pos_next,head) \
   
    for ( pos = (head)->next, pos_next = pos->next; \
   
    pos != (head); \
   
    pos = pos_next, pos_next = pos->next)
   
    #define list_empty(head) (head->next == head)
   
    #define list_entry(ptr, type, member) ((type*)ptr)
   
    #define init_list_head(ptr) \
   
    do{\
   
    (ptr)->prev = ptr; \
   
    (ptr)->next = ptr; \

[1] [2] 下一页

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C语言中强制类型转换总结 下一篇C语言return的使用

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: