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() \n");
longjmp(buf,); 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用法的更多相关文章
- Unix系统编程()执行非局部跳转:setjmp和longjmp
使用库函数setjmp和longjmp可执行非局部跳转(local goto). 术语"非局部(nonlocal)"是指跳转目标为当前执行函数之外的某个位置. C语言里面有个&qu ...
- C语言中setjmp与longjmp学习笔记
C语言中setjmp与longjmp学习笔记 一.基础介绍 头文件:#include<setjmp.h> 原型: int setjmp(jmp_buf envbuf) ,然而longjm ...
- C 语言中 setjmp 和 longjmp
在 C 语言中,我们不能使用 goto 语句来跳转到另一个函数中的某个 label 处:但提供了两个函数——setjmp 和 longjmp来完成这种类型的分支跳转.后面我们会看到这两个函数在处理异常 ...
- 非本地跳转之setjmp与longjmp
非本地跳转(unlocal jump)是与本地跳转相对应的一个概念. 本地跳转主要指的是类似于goto语句的一系列应用,当设置了标志之后,可以跳到所在函数内部的标号上.然而,本地跳转不能将控制权转移到 ...
- 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 ...
- C中的setjmp与longjmp
setjmp与longjmp是属于C语言中的,当然,C++也会有这两个函数了.他们的原型如下: int setjmp( jmp_buf env ); 作用:第一次调佣时,将寄存器的当前状态信息全部存入 ...
- setjmp 与 longjmp
setjmp和longjmp是C语言独有的,只有将它们结合起来使用,才能达到程序控制流有效转移的目的,按照程序员的预先设计的意图,去实现对程序中可能出现的异常进行集中处理. 先来看一下这两个函数的定义 ...
- setjmp和longjmp的使用
问题描述: setjmp和longjmp的使用 问题解决: setjmp和longjmp是C语言独有的,只有将它们结合起来使用,才能达到程序控制流有效转移的目的,按照程序 ...
- 【转】浅析C语言的非局部跳转:setjmp和longjmp
转自 http://www.cnblogs.com/lienhua34/archive/2012/04/22/2464859.html C语言中有一个goto语句,其可以结合标号实现函数内部的任意跳转 ...
随机推荐
- 201521123064 《Java程序设计》第2周学习总结
1. 本章学习总结 1.学会使用码云管理代码,包括将本地的代码上传至码云,和将码云上的项目保存至本地. 2.将码云上项目保存至本地的过程中,若eclipse窗口中已有同名项目,则导入的过程中可能会出错 ...
- 201521123004 《Java程序设计》第10周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 答: 异常的概念上周的思维导图大致体现,这周就归纳一下错误调试 由于多线程的内容比较散,我就直接用文字总结 ...
- 201621123088《Java程序设计》第1周学习总结
1.本周学习总结 以几个关键词描述本周的学习内容.并阐述关键概念之间的联系. 这周是我第一次学习Java,对于我这个上学期没有学好的人来说,Java无疑是一个新的噩梦,但是我相信我这学期一定能学好Ja ...
- 纳税服务系统【自动受理,Quartz任务调度】
需求 回到我们的需求: 自动投诉受理:在每个月月底最后一天对本月之前的投诉进行自动处理:将投诉信息的状态改为 已失效.在后台管理中不能对该类型投诉进行回复. 这个需求需求我们要怎么弄呢????要在每个 ...
- 如何使用Flexbox和CSS Grid,实现高效布局
CSS 浮动属性一直是网站上排列元素的主要方法之一,但是当实现复杂布局时,这种方法不总是那么理想.幸运的是,在现代网页设计时代,使用 Flexbox 和 CSS Grid 来对齐元素,变得相对容易起来 ...
- 西邮linux兴趣小组2014纳新免试题(五)
[第五关] 题目 http://final5.sinaapp.com/ 关注西邮Linux微信平台,得到一个名为a的文件 分析 分析文件a 需要反汇编,拿IDA上,打开后发现key_function及 ...
- java 面向对象 1
目录 一.面向过程的思想和面向对象的思想 二.简单理解面向对象 三.面向对象的设计思想 四.对象和类的概念 五.如何抽象出一个类? 六.类(对象)之间的关系 七.Java与面向对象 八.为什么使用面向 ...
- 如何用kaldi做孤立词识别-初版
---------------------------------------------------------------------------------------------------- ...
- Hive如何添加第三方JAR
以加入elsaticsearch-hadoop-2.1.2.jar为例,讲述在Hive中加入第三方jar的几种方式. 1,在hive shell中加入 [hadoop@hadoopcluster78 ...
- Hbase对时,时差范围的确定
Hbase对时具有严格的要求,集群内部所有机器之间的时差默认不能超过30秒,也就是说,一旦某个regionserver节点上的时间与master节点上的时间差值超过30秒,就会导致相应的regions ...