分享

setjmp和longjmp的用法

 ofirer 2010-12-25

setjmp与longjmp包含在头文件/usr/include/setjmp.h中,使用前应在程序头部加入#include <setjmp.h>。

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

setjmp与longjmp的作用同goto语句类似,它能实现本地的跳转.

 

一.setjmp与logjmp的使用场合:

1.人们对于goto语句的忌讳,很多的专业书籍以及专业人士号召限制goto语句的使用,此时,setjmp与longjmp对goto语句有了很好的替代作用.

2.goto语句有一个局限性,它只能在函数内部跳转.而setjmp与longjmp可以在整个程序全局中跳转,实现"长跳转",弥补了goto功能的局限.

3.使用setjmp和longjmp可以捕捉程序中的异常,并采取异常处理机制.

二.使用setjmp设置跳转点,longjmp回到原设置点

setjmp与longjmp必须结合起来使用;

函数原型:int setjmp(jmp_buf env);

setjmp(env):设置jumper点,jumper是一个jmp_buf类型变量.在setjmp.h文件中有jmp_buf的定义,可见它是一个结构体数组.

/* Calling environment, plus possngibly a saved signal mask.  */

typedef struct __jmp_buf_tag    /* C++ doesn't like tagless structs.  */

{

/* NOTE: The machine-dependent definitions of `__sigsetjmp'

    assume that a `jmp_buf' begins with a `__jmp_buf' and that

    `__mask_was_saved' follows it.  Do not move these members

    or add others before it.  */

__jmp_buf __jmpbuf;     /* Calling environment.  */

    int __mask_was_saved;   /* Saved the signal mask?  */

    __sigset_t __saved_mask;    /* Saved signal mask.  */

} jmp_buf[1];

 

调用该函数对env初始化,初始化后返回一个int值,第一次调用,这个int值为0;

函数原型:void longjmp(jmp_buf env, int val);

第一个参数:setjmp(env)设置的jumper点.

第二个参数:给setjmp(env)重新赋值,为val值.

例:

#include <stdio.h>

#include <setjmp.h>

void subroutine(void);

void subroutine_2(void);

 

jmp_buf jumper;

 

main()

{

    int value;

    int i = 0;

value = setjmp(jumper);   /* 设置jump点,初始化jumper,返回值0赋给value, */

i++;

    printf("执行第[%d]次:value = [%d]: >>>>>>>>>>>>>>>>>>>>>>>>>>>>\n",i,value );

    if(value == 0)

    {

        printf("[1]About to call subroutine.....\n");

        subroutine();  /* 调转到subroutine()函数 */

        printf("Never go this....\n");

    }

    else if(value == 1)

    {

        printf("[2]About to call subroutine.....\n");

        subroutine_2();  /* 调转到subroutine_2()函数 */

        printf("Never go this....\n");

    }

    else

    {

        printf("[3]Never go this....\n");

    }

    return 0;

}

void subroutine(void)

{  

    /* 调转到jumper初始化的地方,即setjmp(jumper)处,并将1赋给set(jumper) */

    longjmp(jumper,1);

    return;

}

void subroutine_2(void)

{  

    /* 调转到jumper初始化的地方,即setjmp(jumper)处,并将3赋给set(jumper) */

    longjmp(jumper,3);

    return;

}

三.使用setjmp,longjmp处理异常.

#include <stdio.h>

#include <setjmp.h>

jmp_buf jumper;

void exception();

int  deal_exception();

main()

{

     int value;

     int i = 0;

     value = setjmp(jumper);   /* 设置jump点,初始化jumper,返回值0赋给value, */

     if ( 0 == value ) {

         exception();

     }

     else {

         switch ( value )

         {

            case 1:

                printf( "解决异常情况[%d]\n",value );

                break;

            case 2:

                printf( "解决异常情况[%d]\n",value );

                break;

            case 3:

                printf( "解决异常情况[%d]\n",value );

                break;

           default:

                printf( "异常情况[%d]未知\n",value );

                break;

        }

    }

}

void exception()

{

    int _err_no;

    if ( _err_no = 3 ) {

        printf("出现异常情况[%d]\n",_err_no);

        longjmp(jumper,_err_no);

    }

    return;

}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多