setjmp和longjmp的使用

int setjmp(jmp_buf envbuf); setjmp函数用缓冲区envbuf保存系统堆栈的内容,以便后续的longjmp函数使用。setjmp函数初次启用时返回0值。

void longjmp(jmp_buf envbuf, int val);

longjmp函数中的参数envbuf是由setjmp函数所保存的堆栈环境,参数val设置setjmp函数的返回值。longjmp函数本身是没有返回值的,它执行后跳转到保存envbuf参数的setjmp函数调用,并由setjmp函数调用返回,此时setjmp函数的返回值就是val。

调用longjmp函数时不能使setjmp函数返回0,如果val为0,则setjmp函数返回1。longjmp函数从来不返回,因为它调用后就跳转到setjmp函数保存的堆栈处,恢复堆栈开始执行,所以longjmp函数不会返回。

setjmp和longjmp函数使用示例:

#include <stdio.h>

#include <setjmp.h>
static jmp_buf buf;
int main()
{
    int b;
    b = 3;
    if (setjmp(buf) != 0) 
    {
        printf("b=%d\n", b); 
        return 0;
    }
    b = 5;
    longjmp(buf, 1);
    return 0;
}

setjmp执行时返回0,执行b等于5,调用longjmp,跳转到setjmp调用,setjmp返回1,打印b=5

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

nt setjmp(jmp_buf  jmpb)设置缓冲区来保存堆栈的内容,将保存的上下文存入进程的自身的数据空间(u区),并继续在当前的上下文中执行,一旦碰到了longjmp,进城就从该进程的u区,取出先前保存的上下文,并恢复该进程的上下文为先前保存的上下文。这时核心将使得进程从setjmp处执行.

void longjmp(jmp_buf jmpb, int retval) 使进程返回到 setjmp处执行,retval表示此时setjmp的返回值。

longjmp必须在setjmp调用之后,而且longjmp必须在setjmp的作用域之内。

jmp_buf的的定义

typedef struct _jmp_buf  
{  
int _jp[_JBLEN+1];  
} jmp_buf[1];

jmp_buf 类型是一个大小为1的数组

传入setjmp中的值是一个结构体的首地址(指针),这同时也说明setjmp必须和处理的内容在同一个函数内,如果单独包装在一个函数内,等函数运行结束运行记录就会丢失,变为NULL,会引发未知后果.

具体来说,在一个函数中使用setjmp来初始化一个全局标号,然后只要该函数未曾返回,那么在其它任何地方都可以通过longjmp调用来跳转到setjmp的下一条语句执行。实际上setjmp函数将发生调用处的局部环境保存在了一个jmp_buf的结构当中,只要主调函数中对应的内存未曾释放(函数返回时局部内存就失效了),那么在调用longjmp的时候就可以根据已保存的jmp_buf参数恢复到setjmp的地方执行。

setjmp函数的返回值(直接返回时为0,longjmp跳转返回时为longjmp的状态参数retval,根据setjmp的返回值就可以判断程序是正常执行还是进行异常处理。

http://hi.baidu.com/passerryan/item/4a468a5ef5a9013394eb0528

 

你可能感兴趣的:(c,c)