setjmp 与 longjmp
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的更多相关文章
- 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的使用 问题解决: setjmp和longjmp是C语言独有的,只有将它们结合起来使用,才能达到程序控制流有效转移的目的,按照程序 ...
- 【转】浅析C语言的非局部跳转:setjmp和longjmp
转自 http://www.cnblogs.com/lienhua34/archive/2012/04/22/2464859.html C语言中有一个goto语句,其可以结合标号实现函数内部的任意跳转 ...
- 【转载】setjmp和longjmp函数使用详解
[说明]本文上半部分转载自 wykwdy007 的转载文章 http://blog.csdn.net/wykwdy007/article/details/6535322 --------------- ...
- 进程环境之setjmp和longjmp函数
在C中,goto语句是不能跨越函数的,而执行这样跳转功能的是函数setjmp和longjmp.这两个函数对于处理发生在深层嵌套函数调用中的出错情况是非常有用的. setjmp和longjmp函数也称为 ...
- setjmp和longjmp函数使用详解
源地址:http://blog.csdn.net/zhuanshenweiliu/article/details/41961975 非局部跳转语句---setjmp和longjmp函数.非局部指的是, ...
随机推荐
- NeHe OpenGL教程 第十课:3D世界
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- 关于maven的一些常见用法
1: 查看插件的目标信息:mvn help:describe 2: 生成javadoc并指定编码:mvn javadoc:javadoc -Dencoding=UTF-8 -Dcharset=UTF- ...
- ylbtech-dbs:ylbtech-1,FAM(家庭资产管理系统)
ylbtech-dbs:ylbtech-1,FAM(家庭资产管理系统) -- =============================================-- Family Assets ...
- Zend Guard Run-time support missing问题的解决
Zend Guard不仅可以实现对PHP应用的脚本进行加密保护和对PHP应用的产品进行商业许可证管理,还可以为许多软件生产商.IT服务提供商提供完善的加密和安全的产品发布系统. 虽然现在可以成功加密p ...
- jsp+bean+servlet 案例代码
包结构图: 代码下载地址
- iOS应用架构谈:架构设计的方法论
缘由 之前安居客iOS app的第二版架构大部分内容是我做的,期间有总结了一些经验.在将近一年之后,前同事zzz在微信朋友圈上发了一个问题:假如问你一个iOS or Android app的架构,你会 ...
- tony_linux下网站压力测试工具webbench
webbench最多可以模拟3万个并发连接去测试网站的负载能力,个人感觉要比Apache自带的ab压力测试工具好,安装使用也特别方便. 1.适用系统:Linux 2.编译安装:wget http:// ...
- 向sqlserver插入二进制数据(比如图片)
sqlserver插入二进制数据 偶然在sqlteam看到了,真是够绝,这都想得出来,很便捷的一个方式(只适用于SQL SERVER 2005+),代码如下: CREATE TABLE myTable ...
- [POJ 1787]Charlie's Change (动态规划)
题目链接:http://poj.org/problem?id=1787 题意:有4种货币分别是1元,5元,10元,20元.现在告诉你这四种货币分别有多少个,问你正好凑出P元钱最多可以用多少货币.每种货 ...
- jxl 导入excel以及日期格式处理
先建一个excel文件abc.xls.放到E盘根目录下.形如下: name secondName hot1 leave1 hot2 leave2 然后在数据库里建表. CREATE TABLE `na ...