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
相关推荐
setjmp 和 longjmp 是 C 语言标准库中的两个函数,用于实现异常处理机制。它们提供了一种非本地局部跳转("non-local goto")机制,能够在程序中实现错误处理模块的调用和返回。 setjmp 函数的作用是保存程序当前的...
1. **Setjump和Longjump**: C语言中,`setjmp()` 和 `longjmp()` 函数是用于实现非局部跳转的,这在一定程度上可以用来模拟异常处理。`setjmp()` 会保存当前环境(包括寄存器状态、堆栈指针等),并返回0。然后,...
4. **SJLJ (SetJump/LongJump) 异常处理**:"sjlj" 指的是 SetJump/LongJump 异常处理机制,它是一种在某些嵌入式和低资源环境下常用的异常处理方式,相对于其他方法可能更占用空间但效率较低。 5. **Runtime (RT)*...
4.2.1是GCC的一个特定版本号,发布于2007年,而“sjlj”可能代表“SetJump/LongJump”调度,这是一种异常处理机制。 描述中同样提到了“gcc-core-4.2.1-sjlj-2.tar.gz”,这进一步确认了这是一个包含GCC核心组件的...
其中的"sjlj"指的是SetJump/LongJump异常处理机制,这是一种在嵌入式系统中常见的异常处理方法。 2. **libnetsim(g++).a**:这是一个静态链接库文件,可能包含用于网络模拟的代码。"libnetsim"暗示了这可能是一个...
在Windows环境中,我们可以利用API函数SetJump和LongJump实现非局部跳转,实现复杂的控制结构。 除此之外,中断处理是汇编语言在Windows环境下的另一个重要话题。系统中断,如INT 21H在DOS时代,或INT 2Eh、INT 33h...
Loomthread 是一个允许多个线程并行运行的库。 它是非标准的、非 posix 的、有限的但意味着要快。 它基于信号处理程序和 setjump/longjump,速度非常快,并且提供了用于同步的互斥锁。
8. **`setjump`** - 保存模型和格局。 9. **`show`** - 显示不同类型的对象信息,如: - `showalarm` - 显示警报信息。 - `showassociation` - 显示关联信息。 - `showattributes` - 显示属性信息。 - `...
此外,控制器还具备了状态变化死区设置,即设置值“SetJUMP”,以及信号通道设置“SetChan”和滤波时间设置“SetFilt”,这些都是为了优化检测精度和稳定性。 在实际应用中,用户可以设置传感头之间的距离值...
/th arena setJump 定义玩家将从何处跳转 玩耍 键入/th join 以加入竞技场。 当有足够的玩家时,游戏将自动开始。 迹象 每个拥有相关权限的玩家都可以创建可点击的标志,以替代玩家命令。 放置一个标志并在第一行...