• setjmp和longjmp用法


    本文转自:http://blog.csdn.net/wuhong40/article/details/6155838,感谢原文作者。

    前不久在阅读Quake3源代码的时候,看到一个陌生的函数:setjmp,一番google和查询后,觉得有必要针对setjmp和longjmp这对函数写一篇blog,总结一下。

    setjmp和longjmp是C语言独有的,只有将它们结合起来使用,才能达到程序控制流有效转移的目的,按照程序员的预先设计的意图,去实现对程序中可能出现的异常进行集中处理。

    先来看一下这两个函数的定义吧:

    setjmp和longjmp的函数原型在setjmp.h中

    函数原型:

     int setjmp(jmp_buf envbuf);

    setjmp函数用缓冲区envbuf保存系统堆栈的内容,以便后续的longjmp函数使用。setjmp函数初次启用时返回0值。

    void longjmp(jmp_buf envbuf, int val);

    longjmp函数中的参数envbuf是由setjmp函数所保存的堆栈环境,参数val设置setjmp函数的返回值。longjmp函数本身是没有返回值的,它执行后跳转到保存envbuf参数的setjmp函数调用,并由setjmp函数调用返回,此时setjmp函数的返回值就是val。

    上面的说明有点拗口,通俗的解释是:先调用setjmp,用变量envbuf记录当前的位置,然后调用longjmp,返回envbuf所记录的位置,并使setjmp的返回值为val。当时用longjmp时,envbuf的内容被销毁了。其实这里的“位置”一词真正的含义是栈定指针。

    接着让我们看一个小例子吧:

    #include <stdio.h> 
    #include <setjmp.h>
    
    jmp_buf buf;
    
    banana(){ 
        printf("in banana() 
    "); 
        longjmp(buf,1);
    
        printf("you'll never see this,because i longjmp'd");
    
    }
    
    main() 
    { 
        if(setjmp(buf)) 
            printf("back in main
    "); 
        else{ 
            printf("first time through
    "); 
            banana(); 
        }
    
    }

    (代码段引自《C专家编程》:p)

    这段代码的打印结果是:

    first time through

    in banana()

    back in main

    仔细看一下应该更能体会这对函数的作用了吧。

    setjmp/longjmp的最大用处是错误恢复,类似try ...catch...

    他们的功能比goto强多了,goto只能在函数体内跳来跳去,而setjmp/longjmp可以在到过的所有位置间。

    从java、.net世界来的兄弟们也许会很不屑于这对函数,也许会觉得这样的功能会使代码的可读性变差。不过请别忘了,这里是C的世界,每个世界有每个世界的哲学,OO只是方法学的一种,而不是全部。quake3是用C写的,据看过其代码的前辈说,其模块化非常好,所以这也是我看quake3代码的初衷。(哦,算了吧,写游戏不是随便说说的...)

    注:

       我第一次看到setjmp是在quake3代码的Com_Init中,

    /* 
    ================= 
    Com_Init 
    ================= 
    */ 
    void Com_Init( char *commandLine ) { 
        char    *s;
    
        Com_Printf( "%s %s %s
    ", Q3_VERSION, CPUSTRING, __DATE__ );
    
        if ( setjmp (abortframe) ) { 
            Sys_Error ("Error during initialization"); 
        }
    
    ....

    卡马克在这里也是当catch用的,其中的一句注释是这么写的:

    jmp_buf abortframe;        // an ERR_DROP occured, exit the entire frame

    继续读吧,在代码中慢慢体会吧...

  • 相关阅读:
    TCP/IP(三)数据链路层~2
    TCP/IP(三)数据链路层~1
    TCP/IP(二)物理层详解
    Maven(六)之依赖管理
    RAID : 独立磁盘冗余阵列(Redundant Array of Independent Disks)
    Oracle启动两个监听
    Oracle服务器修改IP后
    su: cannot set user id: Resource temporarily unavailable
    hadoop报错:java.io.IOException(java.net.ConnectException: Call From xxx/xxx to xxx:10020 failed on connection exception: java.net.ConnectException: 拒绝连接
    spring boot 实现mybatis拦截器
  • 原文地址:https://www.cnblogs.com/hbiner/p/3261437.html
Copyright © 2020-2023  润新知