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 
#include

jmp_buf buf;

banana(){ 
    printf("in banana() \n"); 
    longjmp(buf,1);

printf("you'll never see this,because i longjmp'd");

}

main() 

    if(setjmp(buf)) 
        printf("back in main\n"); 
    else{ 
        printf("first time through\n"); 
        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\n", Q3_VERSION, CPUSTRING, __DATE__ );

if ( setjmp (abortframe) ) { 
        Sys_Error ("Error during initialization"); 
    }

....

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

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

setjmp 与 longjmp的更多相关文章

  1. C 语言中 setjmp 和 longjmp

    在 C 语言中,我们不能使用 goto 语句来跳转到另一个函数中的某个 label 处:但提供了两个函数——setjmp 和 longjmp来完成这种类型的分支跳转.后面我们会看到这两个函数在处理异常 ...

  2. 非本地跳转之setjmp与longjmp

    非本地跳转(unlocal jump)是与本地跳转相对应的一个概念. 本地跳转主要指的是类似于goto语句的一系列应用,当设置了标志之后,可以跳到所在函数内部的标号上.然而,本地跳转不能将控制权转移到 ...

  3. setjmp()、longjmp() Linux Exception Handling/Error Handling、no-local goto

    目录 . 应用场景 . Use Case Code Analysis . 和setjmp.longjmp有关的glibc and eglibc 2.5, 2.7, 2.13 - Buffer Over ...

  4. C中的setjmp与longjmp

    setjmp与longjmp是属于C语言中的,当然,C++也会有这两个函数了.他们的原型如下: int setjmp( jmp_buf env ); 作用:第一次调佣时,将寄存器的当前状态信息全部存入 ...

  5. setjmp和longjmp的使用

    问题描述:          setjmp和longjmp的使用 问题解决:       setjmp和longjmp是C语言独有的,只有将它们结合起来使用,才能达到程序控制流有效转移的目的,按照程序 ...

  6. 【转】浅析C语言的非局部跳转:setjmp和longjmp

    转自 http://www.cnblogs.com/lienhua34/archive/2012/04/22/2464859.html C语言中有一个goto语句,其可以结合标号实现函数内部的任意跳转 ...

  7. 【转载】setjmp和longjmp函数使用详解

    [说明]本文上半部分转载自 wykwdy007 的转载文章 http://blog.csdn.net/wykwdy007/article/details/6535322 --------------- ...

  8. 进程环境之setjmp和longjmp函数

    在C中,goto语句是不能跨越函数的,而执行这样跳转功能的是函数setjmp和longjmp.这两个函数对于处理发生在深层嵌套函数调用中的出错情况是非常有用的. setjmp和longjmp函数也称为 ...

  9. setjmp和longjmp函数使用详解

    源地址:http://blog.csdn.net/zhuanshenweiliu/article/details/41961975 非局部跳转语句---setjmp和longjmp函数.非局部指的是, ...

随机推荐

  1. Report_客制化以PLSQL输出HTML标记实现WEB报表(案例)

    2014-05-31 Created By BaoXinjian

  2. easy dp

    1.将一堆正整数分为2组,要求2组的和相差最小. //File Name: nod1007.cpp //Author: long //Mail: 736726758@qq.com //Created ...

  3. JAVA 想让类无法new,可以使用private将类的构造函数改为私有的,这样new的时候就会报错了

    JAVA 想让类无法new,可以使用private将构造函数改为私有的,这样new的时候就会报错了 主要用于,静态工具类,静态类不需要new,直接使用   类名.静态方法  即可调用 class D{ ...

  4. android之location02

    package com.example.mars_3300_location02; import java.net.ContentHandler; import java.util.List; imp ...

  5. Scroll滚动后发生的改变

    条件:一个panel,足以让panle产生滚动条的N多控件. 动作:拖动滚动条. 影响:呈现在当前panle视图中的控件的Location.Y或Top值>=0,隐藏在滚动条上方的控件的Locat ...

  6. 解决insmod: error inserting 'hello.ko': -1 Invalid module format

    编译自己的内核模块后,insmod出现error:error inserting 'hello.ko': -1 Invalid module format 出现这种情况的原因是因为Makefile种使 ...

  7. java获取本机IP地址和MAC地址的方法

    // 获取ip地址 public static String getIpAddress() { try { Enumeration<NetworkInterface> allNetInte ...

  8. [ActionScript] AS3 绘制虚线

    import flash.geom.Point; import flash.display.MovieClip; import flash.display.Graphics; function dra ...

  9. 理论沉淀:RANSAC算法

    1.解决问题: 当一组样本数据中含有(较小波动的)正常数据(inliers)和(较大波动的)异常数据(outliers)且异常数据的量还不小于正常数据的量时,用最小二乘法将难以获得期望的直线(即能拟合 ...

  10. Nginx作为静态内容服务器(Windows环境)

    1.简单安装 1)下载 http://nginx.org/en/download.html 2)解压后的路径 E:\Study\nginx\nginx-1.7.6 3)执行nginx.exe,访问ht ...