非本地跳转函数setjmp,longjmp, sigsetjmp, siglongjmp

非本地跳转
一种用户级的异常控制流形式。将控制直接从一个函数转移到另一个当前正在执行的函数。不需要正常的调用-返回序列(入栈--出栈)  (ps: 系统调用 为异常中陷阱的主要表现形式, 参数都是 通过通用寄存器而不是栈来传递的
 
重要应用:从一个深层嵌套的函数调用中 立即返回。
 
相关函数:setjmp, longjmp
表头文件:#include <setjmp.h>
函数定义:int setjmp(jmp_buf env)
                 void longjmp(jmp_buf env, int retval);
函数说明:setjmp在env缓存区中保存当前 调用环境(程序计数器、栈指针等) ,以供后面的longjmp使用,并返回0(即第一次设置成功后 返回0,随后由longjmp触发返回后返回longjmp中的参数retval).
longjmp从env中恢复调用环境,然后触发一个从最近一次初始化env的setjmp调用的返回。然后setjmp返回,返回值为longjmp中设置的返回值retval.
setjmp一次调用,多次返回。
参数env为用来保存目前堆栈环境,一般声明为 全局变量

示例:
#include "csapp.h"

jmp_buf buf;
int error1 = 0;
int error2 = 1;
void foo(void), bar(void);

int main()
{
    int rc;

    rc = setjmp(buf);
    if(0 == rc)
        foo();
    else if(1 == rc)
        printf("foo error\n");
    else if(2 == rc)
        printf("bar error\n");
    else
        printf("other error\n");

    return 0;
}

void foo(void)
{
    if(error1)
        longjmp(buf, 1);
    bar();
}

void bar(void)
{
    if(error2)
        longjmp(buf, 2);
}
运行结果:bar error
 
另一个应用:使一个处理信号程序分支跳转到一个特殊的代码位置,而不是 返回到被信号到达中断了的指令的位置。
 
相关函数:sigsetjmp, siglongjmp
表头文件:#include <setjmp.h>
函数定义:int sigsetjmp(sigjmp_buf env, int savesigs)
                 void siglongjmp(jmp_buf env, int retval);
函数说明:sigsetjmp()会保存目前堆栈环境,然后将目前的地址作一个记号,而在程序其他地方调用siglongjmp()时便会直接跳到这个记号位置,然后还原堆栈,继续程序好执行。
参数env为用来保存目前堆栈环境,一般声明为全局变量
参数savesigs若为非0则代表搁置的信号集合也会一块保存
当sigsetjmp()返回0时代表已经做好记号上,若返回非0则代表由siglongjmp()跳转回来。
返回值  :返回0代表已经保存好目前的堆栈环境,随时可供siglongjmp()调用, 若返回非0值则代表由siglongjmp()返回
 
示例:
#include "csapp.h"

sigjmp_buf buf;
void handler(int sig)
{
    siglongjmp(buf, 2);
}

int main()
{
    int rc;
    Signal(SIGINT, handler);
    rc = sigsetjmp(buf, 1);
    if(0 == rc)
        printf("starting\n");
    else if(1 == rc)
        printf("return 1\n");
    else if(2 == rc)
        printf("return 2\n");
    else
        printf("return other\n");

    while(1)
    {
        printf("processing\n");
        sleep(2);
    }
    return 0;
}
测试:ctrl+c 产生中断信号。
信号处理函数 中 根据siglongjmp中retval, 触发 sigsetjmp调用,并返回相应的 retval
测试结果:
starting
processing
processing
return 2  //ctrl+c
processing
processing
processing
processing
return 2  //ctrl+c
processing
....

注:csapp.h  csapp.c可网上搜索并下载

你可能感兴趣的:(异常,非本地跳转)