读书笔记--C语言接口与实现--异常和断言

1.概念

原文

Three kinds of errors occur in programs: user errors, runtime errors, and exceptions。
在程序中有三种错误,用户错误,运行时错误,异常
User errors are expected because they’re likely to occur as the result of erroneous user input.
用户错误被声明是因为有可能是用户输入错误造成的。
The checked runtime errors described in previous chapters are at the other end of the error spectrum. They are not user errors. They are never expected and always indicate program bugs
在最先被描述的可检测的运行时错误是其他一些错误的范围,它们不是用户错误,它们也不会被声明还有就是指明程序错误。
Exceptions occupy the middle ground between user errors and program bugs. An exception is an error that may be rare and perhaps unexpected, but from which recovery may be possible. Some exceptions mirror the cababilities of the machine; examples are arithmetic overflow and underflow and stack overflow. Other exceptions indicate conditions detected by the operating system, perhaps initiated by the user, such as hitting an “interrupt” key or getting a write error while writing a file.
异常介于用户错误和程序错误,一个异常是一个很罕见可能没有被声明的无法修复的错误。一些异常反映了机器的能力,算法的溢出,其他异常被通过操作系统指明,也许被用户初始化,或在写文件是终端。

2. C语言异常检测实现基础知识

setJmp() , longjmp()

非局部跳转语句—setjmp和longjmp函数

非局部指的是,这不是由普通C语言goto,语句在一个函数内实施的跳转,而是在栈上跳过若干调用帧,返回到当前函数调用路径上的某一个函数中。
#include <setjmp.h>
Int setjmp(jmp_buf  env);
   返回值:若直接调用则返回0,若从longjmp调用返回则返回非0值
Void longjmp(jmp_buf env,int val);
    在希望返回到的位置调用setjmp,此位置在main函数中,因为直接调用该函数,所以其返回值为0.setjmp参数evn的类型是一个特殊的类型jmp_buf,这一数据类型是某种形式的数组,其中存放在调用longjmp时能用来恢复栈状态的所有信息。因为需要在另一个函数中引用env变量,所以规范的处理方式是将env变量定义为全局变量。
    jmp_buf 数组类型:
    例如:struct int[16]或struct __jmp_buf_tag,用于保存恢复调用环境所需的信息。
   当检查到一个错误时,则以两个参数调用longjmp函数,第一个就是在调用setjmp时所用的env,第二个参数是具有非0值的val,它将成为从setjmp处返回的值。使用第二个参数的原因是对于一个setjmp可以有多个longjmp
例子:
/* setjmp example: error handling */
#include <stdio.h>    
#include <stdlib.h>    
#include <setjmp.h>     
/* jmp_buf 数据类型, setjmp, longjmp */

int main()
{
  jmp_buf env;
  int val;

  val = setjmp (env);
  if (val) {
    fprintf (stderr,"Error %d happened",val);
    exit (val);
  }
  longjmp (env,101);   /* signaling an error */
  return 0;
}
/*
这个程序利用setjmp 设置捕捉点,然后会被longjmp调用来通知这些错误
输出:
Error 101 happened
*/

3.实现

异常逻辑语句

TRY
S
EXCEPT( e1)
S1
EXCEPT(e2 )

EXCEPT(en )
ELSE
e0
END_TRY

except.h

#ifndef EXCEPT_INCLUDED
#define EXCEPT_INCLUDED
#include <setjmp.h>
#define T Except_T
typedef struct T {
    char *reason;
} T;

struct Except_Frame
{
    struct Except_Frame *prev;
    jmp_buf env;
    const char *file;
    int line;
    const T *exception;
};
typedef struct Except_Frame Except_Frame;
enum {
    Except_entered = 0, Except_raised,
    Except_handled, Except_finalized
};
#define RAISE(e) Except_raise(&(e), __FILE__, __LINE__)
void Except_raise(const T *e, const char *file, int line);
#define TRY do { \
    volatile int Except_flag; \
    Except_Frame Except_frame; \
    Except_frame.prev = Except_stack; \
    Except_stack = &Except_frame;  \
    Except_flag = setjmp(Except_frame.env); \
if (Except_flag == Except_entered) {
#define EXCEPT(e) \
if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
}\
 else if (Except_frame.exception == &(e)) {
     \
     Except_flag = Except_handled;
#define ELSE \
     if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
 }\
 else {
     \
     Except_flag = Except_handled;
#define FINALLY \
     if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
 } { \
     if (Except_flag == Except_entered) \
    Except_flag = Except_finalized;
#define END_TRY \
     if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
 } if (Except_flag == Except_raised) RERAISE; \
} while (0)

#undef T
#endif

yichang.c

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<setjmp.h>
#include<stdlib.h>
#include "assert.h"
#include "except.h"
#include<string.h>
#define T Except_T
#ifdef WIN32
__declspec(thread)
#endif
Except_Frame *Except_stack = NULL;

void Except_raise(const T *e, const char *file,int line) {
    Except_Frame *p = malloc(sizeof(Except_Frame));
       p = Except_stack;
         assert(e);
         if (p == NULL) {
             fprintf(stderr, "Uncaught exception");
             if (e->reason)
                 fprintf(stderr, " %s", e->reason);
             else
                 fprintf(stderr, " at 0x%p", e);
             if (file && line > 0)
                 fprintf(stderr, " raised at %s:%d\n", file, line);
             fprintf(stderr, "aborting...\n");
             fflush(stderr);
             abort();
 }

         p->exception = e;
         p->file = file;
         p->line = line;
         Except_stack = Except_stack->prev;
         longjmp(p->env, Except_raised);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值