一 程序错误分类
在《c语言接口与实现》一书中,将程序的错误分为三类:用户错误、运行时错误和异常。
1、用户错误是预期发生的,主要由错误的用户输入导致。如命名不存在的文件、输入非法的系统格式等。通常,必须要求处理用户错误的函数能返回错误码。
这类错误是系统的一个普通组成部分。
2、运行时错误非预期的,表现为程序出现了bug。因程序无法从这种错误中恢复,而必须优雅地结束。在c语言中这类错误一般通过断言来捕获处理。
3、异常介于用户错误与程序bug之间。异常是比较罕见的错误,但从异常中恢复是有可能的。异常不会频繁发生,因此发生异常的函数通常不返回错误码。
一些异常反映了机器的能力,如算术运算上益和下益;其他异常表明操作系统检测到的状况,如写文件时遇到写入错误、有限资源用尽也可能产所异常,
如应用程序内存不足。
二 异常机制的实现
异常由应用程序产生,由恢复代码处理(如果能恢复)。异常的作用域是动态的:当一个异常被引发时,它由最近实例化的处理程序处理。
在c语言中,可通过setjmp和longjmp函数来建立结构化的异常处理机制。即,setjmp实例化一个处理程序,而longjmp引发一个异常。
libzdb库的异常模块实现与《c语言接口与实现》中的实现基本相同,主要区别在于libzdb应用了线程私有数据,能用于多线程环境。
2.1 相关结构
//Exception.h
#define T Exception_T
#define ThreadData_T pthread_key_t
#define ThreadData_set(key, value) pthread_setspecific((key), (value))
#define ThreadData_get(key) pthread_getspecific((key))
//定义异常
typedef struct T {
const char *name;
}T;
#define EXCEPTION_MESSAGE_LENGTH 512
typedef struct Exception_Frame Exception_Frame;
struct Exception_Frame {
int line;
jmp_buf env;
const char *func;
const char *file;
const T *exception;
Exception_Frame *prev;
char message[EXCEPTION_MESSAGE_LENGTH + 1];//异常消息
};
enum {
Exception_entered = 0,
Exception_thrown,
Exception_handled,
Exception_finalized
};
extern ThreadData_T Exception_stack;//线程私有数据
2.2 初始化
/* -------------------------------------------------------- Privat methods */
static void init_once(void) {
ThreadData_create(Exception_stack);