setjump和longjump

转自:http://www.52rd.com/blog/Detail_RD.Blog_hecrics_16066.html
以前从来没看到过,更别说用了,是不是大家都很少用呢?

int setjmp( jmp_buf env );
void longjmp( jmp_buf env, int value );
 
#     setjmp(j)设置“ jump”点,用正确的程序上下文填充jmp_buf 对象j。这个上下文包括程序存放位置、栈和框架指针,其它重要的寄存器和内存数据。当初始化完jump 的上下文,setjmp()返回0 值。 setjmp 函数的调用时,会保存程序当前的堆栈环境到 env 参数中;
#             以后调用 longjmp(j,r)的效果就是一个“长跳转”到由j 描述的上下文处(也就是到那原来设置j 的setjmp()处)。当作为长跳转的目标而被调用时,setjmp()返回r 或1(如果r 设为0 的话)。(记住,setjmp()不能在这种情况时返回0。
  
       通常 , 用longjmp()来终止异常,用setjmp()标记相应的异常处理程序,  在调用 setjmp 的函数返回之前,调用 longjmp ,否则结果不可预料。
  在使用 longjmp 时,请遵守以下规则或限制:
$     不要假象寄存器类型的变量将总会保持不变。在调用 longjmp 之后,通过 setjmp 所返回的控制流中,例程中寄存器类型的变量将不会被恢复。
$     不要使用 longjmp 函数,来实现把控制流,从一个中断处理例程中传出,除非被捕获的异常是一个浮点数异常。在后一种情况下,如果程序通过调用 _fpreset 函数,来首先初始化浮点数包后,它是可以通过 longjmp 来实现从中断处理例程中返回。
$      C++ 程序中,小心对 setjmp longjmp 的使用,应为 setjmp longjmp 并不能很好地支持 C++ 中面向对象的语义。因此在 C++ 程序中,使用 C++ 提供的异常处理机制将会更加安全。 
   #include   <conio.h>  
  #include   <setjmp.h>  
  void    RaiseException ( jmp_buf   jmpbuf)  
  {  
    printf(   "Press   a   key   to   restore   stack   environment...\n"   )   ;  
    getch()   ;  
    longjmp(jmpbuf, 1);  
}  
 
  int   main()  
  {  
    jmp_buf   jmpbuf   ;  
int   result  ;  
 
     printf(   "Save   stack   environment...\n"   )   ;  
     result   =   setjmp(jmpbuf)   ;  
if( result  ==   0  )  
{
 //Do something
 //If anything wrong.
 RaiseException(jmpbuf)  ;  
}
else// the exception handler, return by longjump, non-zero value
{  
         printf(   "longjump()   returned   %d.\n",   result   )   ;  
         exit(0)   ;  
}
  
    return   0   ;  
  }  
  程序输出将是如下序列: 
  Saving   stack   environment...  
  Call   MyFunc()...  
  Press   a   key   torestore   stack   environment...  
setjmp()   returned   1
//Example 2
#include <stdio.h>
#include <setjmp.h>
 
jmp_buf save;
 
void main()
{
 char c;
 
 for (;; )
{
    switch ( setjmp( save )) 
{
     case 0: /* This is the result from setting up. */
printf ( "Zero returned from setjmp on setup.\n\n");   
break;              
     case 1:
printf ( "NORMAL PROGRAM OPERATION\n\n" );     
break;
     case 2:
printf ( "WARNING\n\n" );     
break;
     case 3:
 printf ( "FATAL ERROR PROGRAM TERMINATED\n\nReally Terminate? y/n: " );
                        fflush ( stdout );           
                         scanf ( "%1s", &c );
                       c  = tolower ( c );       
if ( c == 'y' ) return ( 1 );
                          printf ( "\n" );       break;
        default:     
printf ( "Should never return here.\n" );     
break;
    }
    process ();
 }
}
 
void process ()
{
 int i;
 
 printf ( "Input a number to simulate an error condition: " );
 fflush ( stdout ); scanf ( "%d", &i ); i %= 3;
 i++;                /* So that we call longjmp with 0 < i < 4 */
 longjmp ( save, i);
}

你可能感兴趣的:(setjump和longjump)