嵌入式C编程中的异常处理

      我们今天说说一种典型的实现C语言异常处理的方法,即以setjmp()函数和longjmp()函数实现的异常处理。

        首先我们来了解下什么是异常处理。异常是一个在程序执行期间发生的事件,它中断正在执行的程序的正常的指令流,跳转到异常处理函数中,待异常处理完再跳回到正常的指令流中去。

      我们需要利用两个系统函数,由你自己确定异常处理后返回的地方。接下来我们先看看这两个函数(setjmp()函数和longjmp()函数)是如何实现C语言异常处理。

int setjmp(jmp_buf env)

作用:保存程序的当前运行时的堆栈环境至env中,以供longjmp()函数跳转到此处后恢复上下文环境。

void longjmp(jmp_buf env,int value)

作用:发生异常时,待中断处理函数执行完后,跳转到调用setjmp()函数处,通过之前调用setjmp()函数保存到参数env的数据,恢复上下文环境,同时将value值赋给setjmp()函数,而后主程序正常执行。我们就这样说读者可能就得有点抽象了,那我们还是来看看一段代码后再来分析吧!

testing codes:

#include <stdio.h> 

#include <setjmp.h> 

  jmp_buf buf; 

void handler(void) 

  longjmp(buf,1); 

int main() 

    double a,b; 

    printf("请输入被除数:"); 

    scanf("%lf",&a); 

    printf("请输入除数:"); 

    if(setjmp(buf)==0)  { 

        scanf("%lf",&b); 

        if(0==b)    handler(); 

        printf("相除的结果为:%f\n",a/b); 

    }  else  {

        printf("出现错误除数为0\n"); 

        exit(1);

      }

      return 0; 

}

运行结果为:

请输入被除数:12 

请输入除数:0 

出现错误除数为0 

Press any key to continue 

程序分析:

      在main()函数中,我们最初调用setjmp()函数,保存当前的上下文环境至buf中,同时函数返回0;然后逐步往下运行,运行到我们输入0时,通过if语句发现b的值为0,那么就调用handler()函数来进行处理,在该函数中我们使用了longjmp()函数,我们知道第一个参数的作用是用来得到最初调用setjmp()函数是的环境信息,以便在使用longjmp()函数的时候能够正确的返回到setjmp()函数最初的调用处,而后面的参数表示的返回到setjmp()函数的时候的返回值。我们在此返回1,所以执行else部分的语句。

      值得注意的地方:

1.在setjmp与longjmp结合使用时,它们必须有严格的先后执行顺序,先调用setjmp函数,之后再调用longjmp函数,以恢复到先前被保存的“程序执行点”。否则,假如在setjmp调用之前,执行longjmp函数,将导致程序的执行流变的不可猜测,很轻易导致程序崩溃而退出。

2.源代码中要包含头文件<setjmp.h>

利用signal()函数实现异常处理

      利用signal()函数,系统自动的捕捉到程序执行过程中产生的异常信号,并根据信号类型调用相对应的异常处理函数,处理完之后自动返回到异常发生指令以后,接着执行。接下来我们来看看一段使用signal捕捉除数为0时候的异常代码。

testing codes:

#include <stdio.h>   

#include <signal.h>   

#include <setjmp.h>   

#include <stdlib.h>   

#include <float.h>   

#include <string.h> 

 

jmp_buf buf;             

int  err;           

void handler( int num )   

{   

    err = num;   

    printf( "发生浮点计算异常\n");   

    longjmp( buf, 1);   

int main( void )   

{   

    double a, b;   

    char str[20];   

    int ret; 

    _control87( 0, _MCW_EM ); 

  if( signal( SIGFPE, handler ) == SIG_ERR )  {          printf("绑定失败\n" );   

        abort();     

    } 

    ret = setjmp( buf );   

    if(0 == ret )    {   

        printf("请输入被除数:");   

        scanf("%lf",&a);   

        printf("请输入除数:");   

        scanf("%lf",&b);   

        printf( "a / b = %4.3g\n", a/b);   

        printf("发生异常时候不会被执行的语句\n");   

  } 

  return 0;   

}   

没有发生异常时候的运行结果:

请输入被除数:123 

请输入除数:3 

a / b =  41 

发生异常时候不会被执行的语句 

Press any key to continue 

发生异常时候的运行结果:

请输入被除数:12 

请输入除数:0 

发生浮点计算异常 

Press any key to continue 

程序分析:

          先看看_control87( 0, _MCW_EM );这句,它的功能是开启所有的浮点计算异常,通常情况下浮点计算异常是被屏蔽掉的,我们为了能够使得接下来的signal能够捕捉到浮点计算异常,所以要将其开启。

在往下看我们通过signal( SIGFPE, handler )来绑定了一个浮点计算异常处理函数,如果发生异常时,那么就调用handler()函数来处理。接下来通过ret = setjmp( buf );保存程序运行的环境信息,以便接下来的调用longjmp()函数能够根据这个保存的信息返回该程序先前setjmp()函数的执行点。同时我们对比两次运行的结果发现如果发现异常的时候接下来的打印语句“printf("发生异常时候不会被执行的语句\n");”是不会被执行的,直接跳转到我们绑定的handler()函数执行了。后面我想就不需要我来解释了。

      我们在此仅仅是举一些简单的代码教会读者学会使用setjmp()函数和longjmp()函数来实现异常处理,你完全可以在此基础上编写出复杂的异常处理。


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容