【转载】setjmp和longjmp函数使用详解
【说明】本文上半部分转载自 wykwdy007 的转载文章 http://blog.csdn.net/wykwdy007/article/details/6535322
--------------------------------------------------
非局部跳转语句---setjmp和longjmp函数。非局部指的是,这不是由普通C语言goto,语句在一个函数内实施的跳转,而是在栈上跳过若干调用帧,返回到当前函数调用路径上的某一个函数中。
#include <setjmp.h>
Int setjmp(jmp_buf env);
返回值:若直接调用则返回0,若从longjmp调用返回则返回非0值
Void longjmp(jmp_buf env,int val);
在希望返回到的位置调用setjmp,此位置在main函数中,因为直接调用该函数,所以其返回值为0.setjmp参数evn的类型是一个特殊的类型jmp_buf,这一数据类型是某种形式的数组,其中存放在调用longjmp时能用来恢复栈状态的所有信息。因为需要在另一个函数中引用env变量,所以规范的处理方式是将env变量定义为全局变量。
当检查到一个错误时,则以两个参数调用longjmp函数,第一个就是在调用setjmp时所用的env,第二个参数是具有非0值的val,它将成为从setjmp处返回的值。使用第二个参数的原因是对于一个setjmp可以有多个longjmp。
下面我们可以看一个简单的例子:
void fun1(void); void fun1(void) void fun2(void) |
这个函数的运行结果是:
|
在使用longjmp跳转到setjmp中时,程序主动的退出了!相当于抛出一个异常退出!其实这两个函数可以模拟C++中的异常函数:(vanishfan注:可以类比着理解)
使用setjmp和longjmp要注意以下几点:
1、setjmp与longjmp结合使用时,它们必须有严格的先后执行顺序,也即先调用setjmp函数,之后再调用longjmp函数,以恢复到先前被保存的“程序执行点”。否则,如果在setjmp调用之前,执行longjmp函数,将导致程序的执行流变的不可预测,很容易导致程序崩溃而退出
2、不要假设寄存器类型的变量将总会保持不变。在调用longjmp之后,通过setjmp所返回的控制流中,程序中寄存器类型的变量将不会被恢复。寄存器类型的变量,是指为了提高程序的运行效率,变量不被保存在内存中,而是直接被保存在寄存器中。寄存器类型的变量一般都是临时变量,在C语言中,通过register定义,或直接嵌入汇编代码的程序。这种类型的变量。
longjmp必须在setjmp调用之后,而且longjmp必须在setjmp的作用域之内。(vanishfan注:这两点很重要!)具体来说,在一个函数中使用setjmp来初始化一个全局标号,然后只要该函数未曾返回,那么在其它任何地方都可以通过longjmp调用来跳转到 setjmp的下一条语句执行。实际上setjmp函数将发生调用处的局部环境保存在了一个jmp_buf的结构当中,只要主调函数中对应的内存未曾释放 (函数返回时局部内存就失效了),那么在调用longjmp的时候就可以根据已保存的jmp_buf参数恢复到setjmp的地方执行。
vanishfan注:
【原创】setjmp longjump一些注意点及使用方法
【转载】setjmp和longjmp函数使用详解的更多相关文章
- setjmp和longjmp函数使用详解
源地址:http://blog.csdn.net/zhuanshenweiliu/article/details/41961975 非局部跳转语句---setjmp和longjmp函数.非局部指的是, ...
- 转载 LayoutInflater的inflate函数用法详解
http://www.open-open.com/lib/view/open1328837587484.html LayoutInflater的inflate函数用法详解 LayoutInflater ...
- PHP函数篇详解十进制、二进制、八进制和十六进制转换函数说明
PHP函数篇详解十进制.二进制.八进制和十六进制转换函数说明 作者: 字体:[增加 减小] 类型:转载 中文字符编码研究系列第一期,PHP函数篇详解十进制.二进制.八进制和十六进制互相转换函数说明 ...
- PHP date函数参数详解
PHP date函数参数详解 作者: 字体:[增加 减小] 类型:转载 time()在PHP中是得到一个数字,这个数字表示从1970-01-01到现在共走了多少秒,很奇怪吧 不过这样方便计 ...
- C#虚函数virtual详解
在面向对象编程中,有两种截然不同的继承方式:实现继承和接口继承.在实现继承时候,在Java中,所有函数默认都是virtual的,而在C#中所有函数并不默认为virtual的,但可以在基类中通过声明关键 ...
- Scala进阶之路-Scala函数篇详解
Scala进阶之路-Scala函数篇详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.传值调用和传名调用 /* @author :yinzhengjie Blog:http: ...
- C语言对文件的操作函数用法详解2
fopen(打开文件) 相关函数 open,fclose 表头文件 #include<stdio.h> 定义函数 FILE * fopen(const char * path,const ...
- C语言对文件的操作函数用法详解1
在ANSIC中,对文件的操作分为两种方式,即: 流式文件操作 I/O文件操作 一.流式文件操作 这种方式的文件操作有一个重要的结构FILE,FILE在stdio.h中定义如下: typedef str ...
- 自写函数VB6 STUFF函数 和 VB.net 2010 STUFF函数 详解
'*************************************************************************'**模 块 名:自写函数VB6 STUFF函数 和 ...
随机推荐
- (转)struts2.0配置文件、常量配置详解
一.配置: 在struts2中配置常量的方式有三种: 在struts.xml文件中配置 在web.xml文件中配置 在sturts.propreties文件中配置 1.之所以使用struts.prop ...
- ValueError: Attempted relative import in non-package
执行:python deom/scripts/populate.py ValueError: Attempted relative import in non-package solve:python ...
- POJ3034+DP
题意:给定一个N*N的矩阵, 然后在这个矩阵的每个格子在任意时间会出现一个鼹鼠,这个出现 出现鼹鼠的时间是输出信息所确定的. 现在你手里有一把锤子能够去锤这些鼹鼠. 你能 够移动锤子, ...
- MyBatis的动态SQL操作--删除
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUYAAAC/CAIAAAANX+LCAAAYvElEQVR4nO2dWWycV9nHDyC6UEGBGy
- P127、面试题20:顺时针打印矩阵
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字.例如:如果输入如下矩阵:1 2 3 4 5 6 7 89 10 11 1213 14 15 16则依次打印出 ...
- netty 实现socket服务端编写
import java.net.InetSocketAddress; import io.netty.bootstrap.ServerBootstrap; import io.netty.channe ...
- 第三部分 overlay 学习
前文仅了解了overlay HAL的架构,下面继续看看系统层是如何调用Overlay模块. 1.测试代码 frameworks/base/libs/surfaceflinger/tests/overl ...
- 函数lock_rec_get_nth_bit
/*********************************************************************//** Gets the nth bit of a rec ...
- Java传参那些事!
刚刚学习java传参的时候很纠结,也非常的不理解!课本上的“按值传递”和“按址传递”搞的自己是一头雾水,后来写的项目多了,自然就明白了! 现在写传参几乎就是条件反射一般——“秒成”,分享当初自己为此写 ...
- 学习面试题Day03
1.Java中的注释有哪些? 如果不算Annotation,Java的注释有3种,即行注释.块注释和文档注释.它们往往适合于不同地方的注释,其中文档注释比较特殊,它的注释信息可以进入到javadoc文 ...