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点的返回值冲突了)

  1. #include "apue.h"
  2. #include <setjmp.h>
  3. #define TOK_ADD    5
  4. jmp_buf jmpbuffer;
  5. int
  6. main(void)
  7. {
  8. char    line[MAXLINE];
  9. if (setjmp(jmpbuffer) != 0)
  10. printf("error");
  11. while (fgets(line, MAXLINE, stdin) != NULL)
  12. do_line(line);
  13. exit(0);
  14. }
  15. ...
  16. void
  17. cmd_add(void)
  18. {
  19. int     token;
  20. token = get_token();
  21. if (token < 0)    /* an error has occurred */
  22. longjmp(jmpbuffer, 1);
  23. /* rest of processing for this command */
  24. }

setjump和longjump返回时对auto变量、register变量、volatile变量和静态变量的恢复情况示例。cc -O选项表示编译优化。
longjump返回时一般情况下不会恢复到setjump时的值,此种情况属于未定义。
如果你不想让anto变量的值回滚,需要加上volatile属性。

  1. #include "apue.h"
  2. #include <setjmp.h>
  3. static void f1(int, int, int, int);
  4. static void f2(void);
  5. static jmp_buf jmpbuffer;
  6. static int     globval;
  7. int
  8. main(void)
  9. {
  10. int             autoval;
  11. register int    regival;
  12. volatile int    volaval;
  13. static int      statval;
  14. globval = 1; autoval = 2; regival = 3; volaval = 4; statval = 5;
  15. if (setjmp(jmpbuffer) != 0) {
  16. printf("after longjmp:\n");
  17. printf("globval = %d, autoval = %d, regival = %d,"
  18. " volaval = %d, statval = %d\n",
  19. globval, autoval, regival, volaval, statval);
  20. exit(0);
  21. }
  22. /*
  23. * Change variables after setjmp, but before longjmp.
  24. */
  25. globval = 95; autoval = 96; regival = 97; volaval = 98;
  26. statval = 99;
  27. f1(autoval, regival, volaval, statval); /* never returns */
  28. exit(0);
  29. }
  30. static void
  31. f1(int i, int j, int k, int l)
  32. {
  33. printf("in f1():\n");
  34. printf("globval = %d, autoval = %d, regival = %d,"
  35. " volaval = %d, statval = %d\n", globval, i, j, k, l);
  36. f2();
  37. }
  38. static void
  39. f2(void)
  40. {
  41. longjmp(jmpbuffer, 1);
  42. }
    1. $ cc testjmp.c               compile without any optimization
    2. $ ./a.out
    3. in f1():
    4. globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
    5. after longjmp:
    6. globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
    7. $ cc -O testjmp.c            compile with full optimization
    8. $ ./a.out
    9. in f1():
    10. globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
    11. after longjmp:
    12. globval = 95, autoval = 2, regival = 3, volaval = 98, statval = 99

setjump 和 longjump的更多相关文章

  1. C++自问自答

    1.为什么派生层次上的类,同一个虚函数在各个类的虚表中的位置一样?         因为:对虚函数的调用是通过虚指针+偏移地址构成,由于对虚函数的调用都是通过这种方式,所以对同一个虚函数的偏移值就必须 ...

  2. [转贴]从零开始学C++之异常(一):C语言错误处理方法、C++异常处理方法(throw, try, catch)简介

    一.C语言错误处理方法 1.返回值(if … else语句判断错误) 2.errno(linux 系统调用) 3.goto语句(函数内局部跳转) 4.setjmp.longjmp(Do not use ...

  3. C++编程技术之 异常处理(上)

    增强错误恢复能力是提高代码健壮性的最有力途径之一 之所以平时编写代码的时候不愿意去写错误处理,主要是由于这项工作及其无聊并可能导致代码膨胀,导致的结果就是本来就比较复杂的程序变得更加复杂.当然了,前面 ...

  4. 从零开始学C++之异常(一):C语言错误处理方法、C++异常处理方法(throw, try, catch)简介

    一.C语言错误处理方法 1.返回值(if … else语句判断错误) 2.errno(linux 系统调用) 3.goto语句(函数内局部跳转) 4.setjmp.longjmp(Do not use ...

  5. C错误异常处理,异常处理

    预处理器标识#error的目的是什么啊? 指令 用途 # 空指令,无任何效果 #include 包含一个源代码文件 #define 定义宏 #undef 取消已定义的宏 #if 如果给定条件为真,则编 ...

  6. C语言错误处理方法、C++异常处理方法(throw, try, catch)简介

    一.C语言错误处理方法 1.返回值(if … else语句判断错误) 2.errno(linux 系统调用) 3.goto语句(函数内局部跳转) 4.setjmp.longjmp(Do not use ...

  7. 20170220-coroutine

    协程 coroutine 最近频繁的听说到 "协程" 这个词,花了一段时间肤浅的研究了一下.对于 "它是一个什么东西" 有了一个大概的了解. from wiki ...

  8. 【原创】setjmp longjump一些注意点及使用方法

    setjmp longjump一些注意点及使用方法 jmp_buf结构体的定义 #define _JBLEN  9typedef struct { int _jb[_JBLEN + 1]; } jmp ...

  9. eclipse mingw cpp开发环境

    Eclipse开发c++ 对比:微软的VC++6.0:太老了,对win7兼容不好, 现在微软的Visual Studio:安装包太大,好几个G,装了一堆你不需要的东西,要钱,教 育版申请麻烦 DOS下 ...

随机推荐

  1. HTML5的Web SQL Database

    本文将介绍 Web SQL Database 规范中定义的三个核心方法: openDatabase:这个方法使用现有数据库或新建数据库来创建数据库对象 transaction:这个方法允许我们根据情况 ...

  2. C++ 宽字符(wchar_t)与窄字符(char)的转换

    了解 长度 宽字符wchar_t的长度16位,可以用来显示中文等除英文外的其他文字, 窄字符    char   的长度  8 位,只能处理英文. 哪里可以见到 在VS2010, 2012, 2013 ...

  3. COM 学习小记录

    COM组件程序:模块,它可以是 动态连接库(DLL) && 可执行程序(EXE),称为 进程内组件(in-of-process component) && 进程外组件( ...

  4. 《APUE》第五章练习1

    题目:用setvbuf实现setbuf. 这两个函数都是改变流的缓冲模式的.函数原型如下: #include <stdio.h> void setbuf(FILE *fp, char *b ...

  5. c# 两个数组比较,将重复部分去掉,返回不重复部分

    List<string> Ashuzu = new List<string>(); Ashuzu.Add("); Ashuzu.Add("); List&l ...

  6. DTCMS添加文章,将tags标签的值赋到SEO关键词上,以及将摘要的值赋到SEO描述

    将tags标签的值赋到SEO关键词上 admin\article_edit.aspx中 $(function () {  方法中加上 //tags的值赋到SEO关键词上 $("#txtTag ...

  7. Media Queries——媒体类型

    媒体类型(Media Type)在CSS2中是一个常见的属性,也是一个非常有用的属性,可以通过媒体类型对不同的设备指定不同的样式. 在CSS2中常碰到的就是all(全部).screen(屏幕).pri ...

  8. PHP去掉转义后字符串中的反斜杠\函数stripslashes

    addslashes函数主要是在字符串中添加反斜杠对特殊字符进行转义,stripslashes则是去掉转义后字符串中的反斜杠\,比如当你提交一段 json数据到PHP端的时候可能会遇到json字符串中 ...

  9. 完美解决IE6中fixed抖动问题的方法

    我们可以通过position:fixed来实现元素的固定效果,如网页中底部的"回到顶部菜单",底部的toolbar,对联广告等等,可惜fixed属性在IE6及以下是不支持的.通常的 ...

  10. PHP核心代码库中的APC缓存说明123

    1.APC缓存简介APC,全称是Alternative PHP Cache,官方翻译叫”可选PHP缓存”.它为我们提供了缓存和优化PHP的中间代码的框架. APC的缓存分两部分:系统缓存和用户数据缓存 ...