C语言中的跳转goto&&setjmp&&longjmp sigsetjmp siglongjmp

来源:互联网 发布:js代码测试 编辑:程序博客网 时间:2024/06/10 15:23

C语言中的跳转goto&&setjmp&&longjmp sigsetjmp siglongjmp

分类: C/C++ 159人阅读 评论(1)收藏 举报

1、goto语句,函数内部的短转移

    goto语句只能跳转的到本函数内部的标签处,这个没得说,例子如下:

   

[cpp:nogutter] view plaincopy
  1. #include <stdio.h>  
  2.   
  3. int main()  
  4. {  
  5.         int i=0;  
  6.         loop: printf("do something %d/n",i);  
  7.                 i++;  
  8.                 if(i<6)  
  9.                   goto loop;  
  10.         return 0;  
  11. }  

 2、setjmp 和 longjmp 实现长跳转

     函数原型如下:

     #include <setjmp.h>     

        int setjmp(jmp_buf envbuf);   

        void longjmp(jmp_buf envbuf, int val);

        其中 setjmp用来设置一个供longjmp调至的地址envbuf,初次执行setjmp返回0值,程序继续向下执行,

        当遇到longjmp调用返回到该处是,促使该函数返回val值,这也就是longjmp的第二个参数,通过这种方式

        使得longjmp在跳转的时候可以传递一定的信息给setjmp,可以用来分析跳转原因,方便程序按照不同的返

         回值进行不同的处理。

        

[c-sharp] view plaincopy
  1. #include <setjmp.h>  
  2. #include <stdio.h>  
  3. #include <signal.h>  
  4. jmp_buf buf;  
  5. void handler(int signal)  
  6. {  
  7.   if(signal==SIGINT)  
  8.     printf("Recived SIGINT ,go back to main/n");  
  9.   longjmp(buf,1);  
  10. }  
  11. int main()  
  12. {  
  13.  signal(SIGINT,handler);  
  14.  if(setjmp(buf))  
  15.  {  
  16.    printf("Back in main,infinite loop begins/n");  
  17.  }  
  18.  else  
  19.   printf("infinite loop begins/n");  
  20.  loop:  
  21.    goto loop;  
  22.   
  23. }  

         上面的函数通过在信号捕捉函数中调用longjmp使得程序能返回到main函数继续执行,所以

         setjmp和longjmp的一个很显然的用途就是,从一些非致命行程序错误中返回,使得程序继续 

         执行。

         但是在上面的例子中存在一个问题,当进程第一次接受到SIG_INT信号(Ctrl+C)后成功返回main中,但是

         以后接受到SIG_INT信号却不做任何动作了。原因何在呢?因为:

         调用l o n g j m p时有一个问题。当捕捉到一个信号时,进入信号捕捉函数,此时当前信号被
         自动地加到进程的信号屏蔽字中。这阻止了后来产生的这种信号中断此信号处理程序。如果用
         l o n g j m p跳出此信号处理程序,则对此进程的信号屏蔽字会发生什么呢?一般实现是不会恢复

         原来的信号屏蔽字的,所以SIG_INT信号被屏蔽了,以后不再响应了。

             在4 . 3 + B S D下,s e t j m p和l o n g j m p保存和恢复信号屏蔽字。但是, S V R 4并不
             做这种操作。4 . 3 + B S D提供函数_ s e t j m p和_ l o n g j m p,它们也不保存和恢复信号屏
             蔽字。
        为了允许两种形式并存, P O S I X . 1并没有说明s e t j m p和l o n g j m p对信号屏蔽字的作用,而是
        定义了两个新函数s i g s e t j m p和s i g l o n g j m p。在信号处理程序中作非局部转移时应当使用这两个
        函数。函数原型如下:

         #include <setjmp.h>

           int sigsetjmp( sigjmp_buf * env, intsavemask );

 

 

 

 

 

 

 

           void siglongjmp ( sigjmp_buf * env, int val );

         如果调用sigsetjmp时 参数savemask 为非0,则siglongjmp 从信号处理函数返回时,将恢复进程调用sigsetjmp之前的信号屏蔽字。

        将上面的例子改成使用这对函数,就可以继续对SIG_INT信号进行捕捉和从其中返回main了。

       

[c-sharp] view plaincopy
  1. #include <setjmp.h>  
  2. #include <stdio.h>  
  3. #include <signal.h>  
  4. sigjmp_buf buf;  
  5. void handler(int signal)  
  6. {  
  7.   if(signal==SIGINT)  
  8.     printf("Recived SIGINT ,go back to main/n");  
  9.   siglongjmp(buf,1);  
  10. }  
  11. int main()  
  12. {  
  13.  signal(SIGINT,handler);  
  14.  if(sigsetjmp(buf,1))  
  15.  {  
  16.    printf("Back in main/n");  
  17.  }  
  18.  else  
  19.   printf("infinite loop begins/n");  
  20.  loop:  
  21.    goto loop;  
  22.   
  23. }  

 

 


原创粉丝点击