设为首页 加入收藏

TOP

C语言异常与断言接口与实现(二)
2015-01-22 20:49:51 来源: 作者: 【 】 浏览:38
Tags:语言 异常 断言 接口 实现
my_env, sizeof(jmp_buf)); /* restore exception stack */
? ? ? ? ? ? longjmp(exception_env, exception_type); /* continue handling the exception */
?
? ? ? ? case 0:
? ? ? ? ? ? /* normal, desired operation */
? ? ? ? ? ? second();
? ? ? ? ? ? printf("second succeeded\n"); ?/* not reached */
? ? }
? ? memcpy(exception_env, my_env, sizeof(jmp_buf)); /* restore exception stack */
}
?
void second(void) {
? ? printf("entering second\n" );?
? ? exception_type = 3;
? ? longjmp(exception_env, exception_type);?
? ? printf("leaving second\n");?
}
运行结果:
?
calling first
calling second
entering second
second failed with type 3 exception; remapping to type 1.
first failed, exception type 1
?
接口
Except接口在一系列宏指令和函数中包装了setjmp和longjmp,它们一起提供了一个结构化异常处理工具
?
异常是Except_T类型的一个全局或静态变量:
?
#ifndef EXCEPT_INCLUDED
#define EXCEPT_INCLUDED
#include
#define T Except_T
typedef struct T {
? ? char *reason;
} T;
Except_T结构只有一个字段,它可以初始化为一个描述异常的字符串,当发生一个未处理的异常时,才把字符串打印出来
?
异常处理程序处理的是异常的地址。异常必须是全局的或静态的变量,因此它们的地址唯一地标志了它们,异常e由宏指令引发或由函数引发:
?
#define RAISE(e) Except_raise(&(e), __FILE__, __LINE__)
void Except_raise(const T *e, const char *file,int line);
处理程序是由TRY-EXCEPT和TRY-FINALLY语句来实例化的,这两个语句用宏指令实现,这两个语句可以处理嵌套异常,也可以管理异常状态的数据
?
TRY-EXCEPT的语法是:
?
TRY
?
  S
?
EXCEPT(e1)
?
  S1
?
EXCEPT(e2)
?
  S2
?
……
?
EXCEPT(en)
?
  Sn
?
ELSE
?
  S0
?
END_TRY
?
看下面的代码:
?
int Allocation_handle = 0;
jmp_buf Allocate_Failed;
?
void *allocate(unsigned n)
{
? ? void *new = malloc(n);
? ? if(new)
? ? ? ? return new;
? ? if(Allocation_handle)
? ? ? ? longjmp(Allocate_Failed, 1);
? ? assert(0);
}
?
char *buf;
Allocation_handle = 1;
if(setjmp(Allocate_Failed)) {
? ? fprintf(stderr, "cound't allocate the ?buff\n");
? ? exit(EXIT_FAILURE);
}
buf = allocate(4096);
Allocation_handle = 0;
上面的代码没有提供嵌套的处理程序,Allocation_handle标志的使用也很麻烦。
?
把Allocation_Failed变成一个异常,该异常是在malloc返回一个空指针时由allocate引发:
?
Except_T Allocate_Failed = {"Allocation failed"};
void *allocate(unsigned n)
{
? ? void *new = malloc(n);
? ? if(new)
? ? ? ? return new;
? ? RAISE(Allocation_Failed);
? ? assert(0);
}
如果客户调用程序代码想处理这个异常,那么它需要在TRY-EXCEPT语句内调用allocate:
?
extern Except_T Allocate_Failed;
char *buf;
TRY
? ? buf = allocate(4096);
EXCEPT(Allocate_Failed)
? ? fprintf(stderr, "could't allocate the buff\n");
? ? exit(EXIT_FAILURE);
END_TRY;
TRY-EXCEPT语句是用setjmp和longjmp来实现的
?
TRY-FINALLY语句的语法是:
?
TRY
?
  S
?
FINALLY
?
  S1
?
END_TRY
?
如果S没有产生任何异常,那么执行S1,然后继续执行END_TRY,如果S产生了异常,那么S的执行被中断,控制立即转给S1。S1执行完后,引起S1执行的异常重新产生,使得它可以由前一个实例化的处理程序来处理。注意:S1是在两种情况中都必须执行的,处理程序可以用RERAISE宏指令显示地重新产生异常
?
#define RERAISE Except_raise(Except_frame.exception, \
? ? Except_frame.file, Except_frame.line)
接口中的最后一个宏指令是:
?
#define RETURN switch (Except_stack = Except_stack->prev,0) default: return
RETURN宏指令用在TRY语句的内部,用来代替return语句
?
实现
Except接口中的宏指令和函数一起维护了一个记录异常状态以及实例化处理结构的堆栈。结构中的字段env就是setjmp和longjmp使用的某个jmp_buf,这个堆栈可以处理嵌套的异常
?
typedef struct Except_Frame Except_Frame;
struct Except_Frame {
? ? Except_Frame *prev;
? ? jmp_b
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇数据结构(C实现)------- 遍历二.. 下一篇C语言指针――指针的运算

评论

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