setjump 和 longjump
goto语句可以用于同一个函数内异常处理,不幸的是,goto是本地的,它只能跳到所在函数内部的标号上。为了解决这个限制,C函数库提供了setjmp()和longjmp()函数,它们分别承担非局部标号和goto作用。头文件<setjmp.h>申明了这些函数及同时所需的jmp_buf数据类型。
1.setjmp(jbuf)设置“jump”点,用正确的程序上下文填充jmp_buf对象jbuf。这个上下文包括程序存放位置、栈和框架指针,其它重要的寄存器和内存数据。当初始化完jump的上下文,setjmp()返回0值。
2. 以后调用longjmp(jbuf,r)的效果就是一个非局部的goto或“长跳转”到由jbuf描述的上下文处(也就是到那原来设置jbuf的setjmp()处)。当作为长跳转的目标而被调用时,setjmp()返回r (或1,如果r设为0的话)。(setjmp()不能在这种情况时返回0,否则就和设置jump点的返回值冲突了)
- #include "apue.h"
- #include <setjmp.h>
- #define TOK_ADD 5
- jmp_buf jmpbuffer;
- int
- main(void)
- {
- char line[MAXLINE];
- if (setjmp(jmpbuffer) != 0)
- printf("error");
- while (fgets(line, MAXLINE, stdin) != NULL)
- do_line(line);
- exit(0);
- }
- ...
- void
- cmd_add(void)
- {
- int token;
- token = get_token();
- if (token < 0) /* an error has occurred */
- longjmp(jmpbuffer, 1);
- /* rest of processing for this command */
- }
setjump和longjump返回时对auto变量、register变量、volatile变量和静态变量的恢复情况示例。cc -O选项表示编译优化。
longjump返回时一般情况下不会恢复到setjump时的值,此种情况属于未定义。
如果你不想让anto变量的值回滚,需要加上volatile属性。
- #include "apue.h"
- #include <setjmp.h>
- static void f1(int, int, int, int);
- static void f2(void);
- static jmp_buf jmpbuffer;
- static int globval;
- int
- main(void)
- {
- int autoval;
- register int regival;
- volatile int volaval;
- static int statval;
- globval = 1; autoval = 2; regival = 3; volaval = 4; statval = 5;
- if (setjmp(jmpbuffer) != 0) {
- printf("after longjmp:\n");
- printf("globval = %d, autoval = %d, regival = %d,"
- " volaval = %d, statval = %d\n",
- globval, autoval, regival, volaval, statval);
- exit(0);
- }
- /*
- * Change variables after setjmp, but before longjmp.
- */
- globval = 95; autoval = 96; regival = 97; volaval = 98;
- statval = 99;
- f1(autoval, regival, volaval, statval); /* never returns */
- exit(0);
- }
- static void
- f1(int i, int j, int k, int l)
- {
- printf("in f1():\n");
- printf("globval = %d, autoval = %d, regival = %d,"
- " volaval = %d, statval = %d\n", globval, i, j, k, l);
- f2();
- }
- static void
- f2(void)
- {
- longjmp(jmpbuffer, 1);
- }
- $ cc testjmp.c compile without any optimization
- $ ./a.out
- in f1():
- globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
- after longjmp:
- globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
- $ cc -O testjmp.c compile with full optimization
- $ ./a.out
- in f1():
- globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
- after longjmp:
- globval = 95, autoval = 2, regival = 3, volaval = 98, statval = 99
setjump 和 longjump的更多相关文章
- C++自问自答
1.为什么派生层次上的类,同一个虚函数在各个类的虚表中的位置一样? 因为:对虚函数的调用是通过虚指针+偏移地址构成,由于对虚函数的调用都是通过这种方式,所以对同一个虚函数的偏移值就必须 ...
- [转贴]从零开始学C++之异常(一):C语言错误处理方法、C++异常处理方法(throw, try, catch)简介
一.C语言错误处理方法 1.返回值(if … else语句判断错误) 2.errno(linux 系统调用) 3.goto语句(函数内局部跳转) 4.setjmp.longjmp(Do not use ...
- C++编程技术之 异常处理(上)
增强错误恢复能力是提高代码健壮性的最有力途径之一 之所以平时编写代码的时候不愿意去写错误处理,主要是由于这项工作及其无聊并可能导致代码膨胀,导致的结果就是本来就比较复杂的程序变得更加复杂.当然了,前面 ...
- 从零开始学C++之异常(一):C语言错误处理方法、C++异常处理方法(throw, try, catch)简介
一.C语言错误处理方法 1.返回值(if … else语句判断错误) 2.errno(linux 系统调用) 3.goto语句(函数内局部跳转) 4.setjmp.longjmp(Do not use ...
- C错误异常处理,异常处理
预处理器标识#error的目的是什么啊? 指令 用途 # 空指令,无任何效果 #include 包含一个源代码文件 #define 定义宏 #undef 取消已定义的宏 #if 如果给定条件为真,则编 ...
- C语言错误处理方法、C++异常处理方法(throw, try, catch)简介
一.C语言错误处理方法 1.返回值(if … else语句判断错误) 2.errno(linux 系统调用) 3.goto语句(函数内局部跳转) 4.setjmp.longjmp(Do not use ...
- 20170220-coroutine
协程 coroutine 最近频繁的听说到 "协程" 这个词,花了一段时间肤浅的研究了一下.对于 "它是一个什么东西" 有了一个大概的了解. from wiki ...
- 【原创】setjmp longjump一些注意点及使用方法
setjmp longjump一些注意点及使用方法 jmp_buf结构体的定义 #define _JBLEN 9typedef struct { int _jb[_JBLEN + 1]; } jmp ...
- eclipse mingw cpp开发环境
Eclipse开发c++ 对比:微软的VC++6.0:太老了,对win7兼容不好, 现在微软的Visual Studio:安装包太大,好几个G,装了一堆你不需要的东西,要钱,教 育版申请麻烦 DOS下 ...
随机推荐
- SQL 的一个技巧
遇到一个需求,项目是我接手二次开发的,之前的大神设计数据库,订单表中没有订单号,现在让我加上这个号,规则是订单创建日期加上自增的ID,ID需要补足5位,例:00002,00124,01245这样.这个 ...
- ios Swift 之github
1. 软件类 a) 作者集合 http://nondot.org/sabre/ b) swift for facebook SWIFT是一个易于使用的,基于注解的Java来创建勤俭节约序列化类型和服务 ...
- 第三十八篇、给UITabBar按钮的动画效果
在很多情况下,我们也时常有这样的需求,就是在UITabBar切换的时候,添加一些动画效果 1.在UITabBar触发点击方法的时候捕获当前点击的item 2.使用coreAnimation设置动画效果 ...
- 【转】C# 后台开启 cmd执行命令
private void RunCmd(string cmd) { System.Diagnostics.Process p = new System.Diagnostics. ...
- GIS初学者
学习编程一直以来没有什么好的思路,感觉就是学了忘,忘了再重复,效率特别低下.大概是从大三第一学期才有意识的转向c#的学习,来熟悉VS2010平台,在这之前我都不知道自己是怎么学习的. 大一第二学期开的 ...
- 分类算法之贝叶斯(Bayes)分类器
摘要:旁听了清华大学王建勇老师的 数据挖掘:理论与算法 的课,讲的还是挺细的,好记性不如烂笔头,在此记录自己的学习内容,方便以后复习. 一:贝叶斯分类器简介 1)贝叶斯分类器是一种基于统计的分类器 ...
- ▲▲▲▲▲▲▲▲▲▲▲yum源的配置(本地和ftp)▲▲▲▲▲▲▲▲▲▲▲▲▲v
★★★★★★★★★★★★★★★本机yum源★★★★★★★★★★★★★★★★ 1. 首先把DVD里的OS镜像mount处理,如果插入光驱自动mount的话,一般在/media下面,比如RHEL_6.3 ...
- TweenMax动画库学习(六)
目录 TweenMax动画库学习(一) TweenMax动画库学习(二) TweenMax动画库学习(三) Tw ...
- NHibernate各种查询
NHibernate各种查询 NHibernate's methods of querying are powerful, but there's a learning curve. Longer t ...
- 非常出色的一款WinForm窗体重绘GUI类库源码
基本控件的演示 ScrollBar滚动条 各种圆形进度条 ProgressBar进度条 Mdi演示,仿谷歌浏览器 多种皮肤可供选择 一套专业级别的GUI控件,目前包含了窗体.进度条.滚动条以及MDI多 ...