setjmp/longjmp 使用
C语言中有一个goto语句,其可以结合标号实现函数内部的任意跳转(通常情况下,很多人都建议不要使用goto语句,因为采用goto语句后,代码维护工作量加大)。另外,C语言标准中还提供一种非局部跳转“no-local goto",其通过标准库<setjmp.h>中的两个标准函数setjmp和longjmp来实现。
C标准库<setjmp.h>
下面是K&R的《C程序设计语言(第2版 . 新版)》第232页给出的关于标准库<setjmp.h>的说明。
非局部跳转<setjmp.h> 头文件<setjmp.h>中的说明提供了一种避免通常的函数调用和返回顺序的途径,特别的,它允许立即从一个多层嵌套的函数调用中返回。 8.1 setjmp #include <setjmp.h>
int setjmp(jmp_buf env); setjmp()宏把当前状态信息保存到env中,供以后longjmp()恢复状态信息时使用。如果是直接调用setjmp(),那么返回值为0;如果是由于调用longjmp()而调用setjmp(),那么返回值非0。setjmp()只能在某些特定情况下调用,如在if语句、 switch语句及循环语句的条件测试部分以及一些简单的关系表达式中。 8.2 longjmp #include <setjmp.h>
void longjmp(jmp_buf env, int val); longjmp()用于恢复由最近一次调用setjmp()时保存到env的状态信息。当它执行完时,程序就象setjmp()刚刚执行完并返回非0值val那样继续执行。包含setjmp()宏调用的函数一定不能已经终止。所有可访问的对象的值都与调用longjmp()时相同,唯一的例外是,那些调用setjmp()宏的函数中的非volatile自动变量如果在调用setjmp()后有了改变,那么就变成未定义的。
cplusplus:
int setjmp (jmp_buf env);
This macro with functional form fills env with information about the current state of the calling environment in that point of code execution, so that it can be restored by a later call to longjmp.
Calling longjmp with the information stored in env restores this same state and returns the control to that same point (the call to setjmp), which is evaluated as a particular non-zero value.
The state of the calling environment includes the values of all accessible objects, except those of automatic duration local to the function which do not have volatile
-qualified types and which change before the call tolongjmp; these have indeterminate values.
The invocation of setjmp shall be an expression statement by itself, or be evaluated in a selection or iteration statement either as the (potentially negated) entire controlling expression or compared against an integer constant expression. Otherwise, it causes undefined behavior.
Parameters
- env
- Object of type jmp_buf where the environment information is stored.
Return Value
This macro may return more than once: A first time, on its direct invocation; In this case it always returns zero.
When longjmp is called with the information set to env, the macro returns again; this time it returns the value passed to longjmp as second argument if this is different from zero, or 1
if it is zero.
void longjmp (jmp_buf env, int val);
Restores the environment to the state indicated by env, evaluating the setjmp expression that filled env as val.
The function never returns to the point where it has been invoked. Instead, the function transfers the control to the point where setjmp was last used to fill the env, and evaluates the whole expression as val (unless this is zero, in which case it evaluates as value of 1
).
If env was not filled by a previous call to setjmp or if the function with such call has terminated execution, it causesundefined behavior.
In C++, the implementation may perform stack unwinding that destroys objects with automatic duration. If this invokes any non-trivial destructors, it causes undefined behavior.
Parameters
- env
- Object of type jmp_buf filled by a previous call to setjmp that contains information to restore the environment to that point.
- val
- Value to which the setjmp expression evaluates.
If this is zero, the expression evaluates as1
.
/* setjmp example: error handling */
#include <stdio.h> /* printf, scanf */
#include <stdlib.h> /* exit */
#include <setjmp.h> /* jmp_buf, setjmp, longjmp */ main()
{
jmp_buf env;
int val; val = setjmp (env);
if (val) {
fprintf (stderr,"Error %d happened",val);
exit (val);
} /* code here */ longjmp (env,); /* signaling an error */ return ;
}
The function uses setjmp to set up a catch-point that can later be called by longjmp to signal errors.
Output:
error 101 happended
setjmp.h是C标准函数库中提供“非本地跳转”的头文件:控制流偏离了通常的子程序调用与返回串行。互补的两个函数setjmp与longjmp提供了这种功能。
setjmp/longjmp的典型用途是异常处理机制的实现:利用longjmp恢复程序或线程的状态,甚至可以跳过栈中多层的函数调用。
setjmp
保存当前的环境(即程序的状态)到平台相关的一个数据结构 (jmp_buf
),该数据结构在随后程序执行的某一点可被 longjmp
用于恢复程序的状态到setjmp
调用所保存到jmp_buf
时的原样。这一过程可以认为是"跳转"回setjmp
所保存的程序执行状态。setjmp
的返回值指出控制是正常到达该点还是通过调用longjmp
恢复到该点。因此有编程的惯用法:
if( setjmp(x) ){/* handle longjmp(x) */}
。
#include <stdio.h>
#include <setjmp.h> static jmp_buf buf; void second(void) {
printf("second\n"); // 打印
longjmp(buf,); // 跳回setjmp的调用处 - 使得setjmp返回值为1
} void first(void) {
second();
printf("first\n"); // 不可能执行到此行
} int main() {
if ( ! setjmp(buf) ) {
first(); // 进入此行前,setjmp返回0
} else { // 当longjmp跳转回,setjmp返回1,因此进入此行
printf("main\n"); // 打印
} return ;
}
上述程序将输出:
second
main
注意到虽然first()
子程序被调用,"first
"不可能被打印。"main
"被打印,因为条件语句if ( ! setjmp(buf) )
被执行第二次。
更多:
http://zh.wikipedia.org/wiki/Setjmp.h
http://blog.codingnow.com/2010/05/setjmp.html
setjmp/longjmp 使用的更多相关文章
- Linux setjmp longjmp
/********************************************************************* * Linux setjmp longjmp * 说明: ...
- 函数 setjmp, longjmp, sigsetjmp, siglongjmp
一,相关函数接口 1,setjmp,longjmp,sigsetjmp,siglongjmp #include <setjmp.h> int setjmp(jmp_buf env); ...
- setjmp/longjmp
1.setjmp/longjmp属于传统的错误处理 2.setjmp/longjmp是对goto语句的补充,goto仅仅能实现局部跳转.setjmp/longjmp能够实现全局跳转 3.setjmp/ ...
- c setjmp longjmp
http://coolshell.cn/?s=setjmp http://www.cnblogs.com/hazir/p/c_setjmp_longjmp.html double divide(dou ...
- goto语句的升级版,setjmp,longjmp
我们知道goto语句是不能跳过函数的,但是在我么C语言的应用中,在不使用汇编的情况下,遇到需要跳出深层循环比如检错机制的时候,有确实想要跨函数跳转,有没有上面办法可以做到呢? 这就是今天要讲的两个库函 ...
- 信号处理函数的返回setjmp/longjmp
信号处理函数可以正常返回,也可以调用其他函数返回到程序的主函数中,而不是从该处理程序返回. 正如ANSI C标准所说明的,一个信号处理程序可以返回或者调用abort.exit或longjmp(goto ...
- setjmp/longjmp 处理异常
#include <stdio.h> #include <stdlib.h> #include <setjmp.h> jmp_buf jb; void f1() { ...
- setjmp()/longjmp()的使用方法
setjmp和longjmp.为了让你实现复杂的流控制,程序在系统里面运行完全依靠内存(代码段,全局段,堆存储器,栈存储器)和寄存器的内容(栈指针,基地址,计数器),setjmp保存当前的寄存器里面的 ...
- 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 ...
随机推荐
- PHP读取文件头(2字节)判断文件类型(转)
看到此标题或许你会说是否是多此一举,直接判断扩展名不就知道文件类型了吗,但是扩展名很容易伪造,这样就绕过了判断.大部分的文件都会将一个特殊的数字或字符存放在文件的特定位置里(开始处的2个字节) /** ...
- Excel VBA批量修改文件夹下的文件名
今天,有同事提出想批量修改文件名,规则比较简单,在第五位后加“-”即可, 上网没找到相关工具,就自己做了个excel,用宏代码修改. 代码如下: Private Sub CommandButton1_ ...
- Java——(三)Collection之Set集合、HashSet类
------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.Set集合 Set集合不允许包含相同的元素,如果试图把两个相同的元素加入同一个Set集合中, ...
- mac 终端常见指令
基本命令 1.列出文件 ls 参数 目录名 例: 看看驱动目录下有什么:ls /System/Library/Extensions参数 -w 显示中文,-l 详细信息, -a 包括隐藏文 ...
- typeerror $.ajax is not a function
在web开发中使用jQuery进行前端开发遇到这么个问题,纠结了很久终于解决了,下面说一下解决方法. 大家可以参照下面几种排查的方法. 1.首先检查是否引用jQuery的库. 2.页面如果使用的ifr ...
- HTML5小游戏源码收藏
html5魅族创意的贪食蛇游戏源码下载 html5网页版打砖块小游戏源码下载 html5 3D立体魔方小游戏源码下载 html5网页版飞机躲避游戏源码下载 html5三国人物连连看游戏源码下载 js ...
- angularJS function
angular.bootstrap 启动Angular angular.element 相当于轻量的JQuery 使用方法: angular.element('#qq'); angular.eleme ...
- Quartz.NET配置(Log4net)
最近有个任务关于服务调度,想起以前看过Quartz.NET调度任务非常棒. 今天小试Quartz.NET,前面配置Quartz.NET很轻松,控制台也输出了.但是想配合Log4net来做日志文件,怎么 ...
- C蛮的全栈之路-node篇(一) 环境布置
目录 C蛮的全栈之路-序章 技术栈选择与全栈工程师C蛮的全栈之路-node篇(一) 环境布置C蛮的全栈之路-node篇(二) 实战一:自动发博客 ---------------- 我是分割线 ---- ...
- SGU 111.Very simple problem
题目大意: 求平方不大于n(n<=10^1000)的最大的数. 分析: 二分+高精度乘法 或者 高精度开方... ...