linux 跳转 setjmp longjmp

setjmp.h is a header defined in the C standard library to provide "non-local jumps": control flow that deviates from the usual subroutine call and return sequence. The complementary functionssetjmp and longjmp provide this functionality.

A typical use of setjmp/longjmp is implementation of anexception mechanism that exploits the ability of longjmp to reestablish program or thread state, even across multiple levels of function calls. A less common use ofsetjmp is to create syntax similar to coroutines.

Member functions

int setjmp(jmp_buf env)Sets up the local jmp_buf buffer and initializes it for the jump. This routine[1] saves the program's calling environment in the environment buffer specified by theenv argument for later use by longjmp. If the return is from a direct invocation,setjmp returns 0. If the return is from a call to longjmp,setjmp returns a nonzero value.
void longjmp(jmp_buf env, int value)Restores the context of the environment buffer env that was saved by invocation of thesetjmp routine[1] in the same invocation of the program. Invoking longjmp from a nested signal handler is undefined. The value specified by value is passed from longjmp tosetjmp. After longjmp is completed, program execution continues as if the corresponding invocation ofsetjmp had just returned. If the value passed to longjmp is 0, setjmp will behave as if it had returned 1; otherwise, it will behave as if it had returnedvalue.

 

setjmp saves the current environment (i.e., the program state) at some point of program execution, into a platform-specific data structure (jmp_buf) which can be used, at some later point of program execution, bylongjmp to restore the program state to that which was saved by setjmp into jmp_buf. This process can be imagined to be a "jump" back to the point of program execution wheresetjmp saved the environment. The (apparent) return value from setjmp indicates whether control reached that point normally or from a call tolongjmp. This leads to a common idiom: if( setjmp(x) ){/* handle longjmp(x) */}.

POSIX.1 does not specify whethersetjmp and longjmp save or restore the current set of blockedsignals — if a program employs signal handling it should use POSIX's sigsetjmp/siglongjmp.

Member types

jmp_bufAn array type, such as struct __jmp_buf_tag[1],[2] suitable for holding the information needed to restore a calling environment.


The C99 Rationale describes jmp_buf as being an array type for backwards compatibility; existing code refers to jmp_buf storage locations by name (without the& address-of operator), which is only possible for array types.[3]

Caveats and limitations

When a "non-local goto" is executed via setjmp/longjmp, normal "stack unwinding" does not occur. Therefore any required cleanup actions will not occur either. This could include closing file descriptors, flushing buffers, or freeing heap-allocated memory.

If the function in which setjmp was called returns, it is no longer possible to safely uselongjmp with the corresponding jmp_buf object. This is because thestack frame is invalidated when the function returns. Calling longjmp restores thestack pointer, which—because the function returned—would point to a non-existent and potentially overwritten or corrupted stack frame.[4][5]

Similarly, C99 does not require that longjmp preserve the current stack frame. This means that jumping into a function which was exited via a call tolongjmp is undefined.[6] However, most implementations of longjmp leave the stack frame intact, allowing setjmp andlongjmp to be used to jump back-and-forth between two or more functions—a feature exploited formultitasking.

Compared to mechanisms in higher-level programming languages such as Python, Java, C++, C#, and even pre-C languages such as Algol 60, the technique of using setjmp/longjmp to implement an exception mechanism is cumbersome. These languages provide more powerfulexception handling techniques, while languages such as Scheme, Smalltalk, and Haskell provide even more general continuation-handling constructs.

example:

#include  <stdio.h>
#include  <stdlib.h>
#include  <setjmp.h>
jmp_buf buf;

void banana()
{ 
    printf("in banana() \n"); 
    longjmp(buf,2);
    printf("you'll never see this,because i longjmp'd");

}

main() 
{ 
	int rvalu;
	rvalu = setjmp(buf);
    if(rvalu) 
    {
        printf("back in main\n"); 
        printf("return value is %d\n", rvalu); //输出值为,longjmp的第二个参数的值,可根据这个值,判断发生异常的事情
	}
    else
    { 
        printf("first time through\n"); 
        banana(); 
    }

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
setjmplongjmp是C语言中提供的两个非常重要的函数,目的是实现函数间的跳转和状态保存。 setjmp函数用于保存当前函数执行的上下文,同时返回一个int类型的值。这个值由setjmp函数自动生成,用于之后调用longjmp函数时确定跳转目标。 longjmp函数则用于恢复之前setjmp所保存下来的上下文,使得程序能够直接跳转到指定的目标。 下面是setjmplongjmp在mips汇编语言中的实现: setjmp: ``` #setjmp implementation in MIPS assembly language .text .align 2 .globl setjmp .ent setjmp setjmp: addi sp, sp, -32 # allocate stack frame sw ra, 28(sp) # save return address sw fp, 24(sp) # save frame pointer addi fp, sp, 32 # set new frame pointer sw a0, 0(fp) # save jmp_buf li v0, 0 # return 0 jr ra .end setjmp ``` longjmp: ``` #longjmp implementation in MIPS assembly language .text .align 2 .globl longjmp .ent longjmp longjmp: lw fp, 24(sp) # restore frame pointer lw ra, 28(sp) # restore return address addi sp, sp, 32 # deallocate stack frame lw t0, 0(fp) # restore jmp_buf lw ra, 4(t0) # restore return address lw sp, 8(t0) # restore stack pointer lw s0, 12(t0) # restore frame pointer jr ra .end longjmp ``` 以上是setjmplongjmp在MIPS汇编语言中的实现。需要注意的是,这里使用了MIPS体系结构的调用约定,即函数返回值在v0寄存器中,函数参数在a0-a3寄存器中,被调用者保存的寄存器在栈帧中。在实际使用中,应根据特定的编译器和操作系统的要求进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值