• C异常处理机制:setjmp和longjmp(转)


    setjmp()和longjum()是通过操纵过程活动记录实现的。它是C语言所独有的。它们部分你不了C语言有限的转移能力。这个两个函数协同工作,如下所示:
        *setjmp(jmp_buf j)必须首先被调用。它表示“使用变量j记录现在的位置。函数返回零。”
        *longjmp(jmp_buf j,int i)可以接着被调用。它表示“回到j所记录的位置,让它看上去像是从原来的setjmp()函数返回一样。但是函数返回i,使代码知道它实际上是通过longjmp()返回的。“坳口不?
        *当使用longjmp()时,j的内容被销毁。
        setjmp保存了一份程序的计数器和当前的栈顶指针。如果喜欢也可以保存一些初始值。longjmp恢复这些值,有效的转移控制并把状态重置回保存状态 的时候。这被称做“展开堆栈(unwinding stack)",因为你从堆栈中展开过程活动记录,直到取得保存在其中的值。尽管longjmp会导致转移,但它和goto又有不同,区别如下:
        *goto语句不能跳出C语言当前的函数(这也是“longjmp”取名的由来,它可以跳的很远,甚至可以跳到其他文件的函数中)。
        *用longjmp只能跳回到曾经到过的地方。在setjmp的地方仍留有一个过程活动记录。从这个角度讲,longjmp更像是“从何处阿里(come from)“而不是”往哪里去(go to)”。longjmp接受一个额外的整型参数并返回它的值,这可以知道是由longjmp转移到这里的还是从上条语句执行后自然而然来的这里的。
        下面的代码显示了setjmp()和longjmp()一例。

    #include <stdio.h>
    #include <setjmp.h>
     jmp_buf buf;
     
    banana()
     {
             printf("%s","in banana() \n");
             longjmp(buf,1);
             printf("%s","you will never see this \n");
     }
     
     int main() 
    {
             if(setjmp(buf))
             { 
                 printf("%s","back in main\n");
             }
             else
             {
                 printf("%s","first time throught\n");
                 banana();
             }
     }
    


        输出结果如下:
        first time throught
        in banana()
        back in main
        需要注意的地方是:保证局部变量在longjmp过程中一直保持它的值的唯一可靠方法是把它声明为volatile(这使用于那些值在setjmp执行和longjmp返回之间会改变的变量)
        setjmp/longjmp最大的用途是错误恢复。只要还没有从函数中返回,一旦发现一个不可恢复的错误,可以把控制转移到主输入循环,并从那里重新开 始。有些人使用setjmp/longjmp从一串无数的函数调用中立即返回。还有些人用它们防范潜在的危险代码。
        setjmp/longjmp在C++中演变为更普通的异常处理机制"catch"和"throw"。

  • 相关阅读:
    二分图的部分关系
    二分图的部分关系
    日常训练赛 Problem C – Complete Naebbirac’s sequence
    日常训练赛 Problem C – Complete Naebbirac’s sequence
    J
    J
    Python strip()方法
    Python startswith()方法
    Python splitlines()方法
    Python split()方法
  • 原文地址:https://www.cnblogs.com/doctorqbw/p/2495195.html
Copyright © 2020-2023  润新知