进程环境之setjmp和longjmp函数


在C中,goto语句是不能跨越函数的,而执行这样跳转功能的是函数setjmp和longjmp。这两个函数对于处理发生在深层嵌套函数调用中的出错情况是非常有用的。

setjmp和longjmp函数也称为非局部goto,非局部指的是,这不是由普通C语言goto语句在一个函数内实施的跳转,而是在栈上跳过若干调用帧,返回到当前函数调用路径上的某一函数中。

#include <setjmp.h>

 longjmp( jmp_buf env,  val );

 

<setjmp.h>( setjmp(jmpbuffer) != ( ... )

执行main时,调用setjmp,它将所需的信息记入变量jmpbuffer中并返回0。然后调用do_line,它又调用cmd_add,假定在其中检查到一个错误。在cmd_add中调用longjmp之前,栈的形式如图7-4所示。但是longjmp使栈反绕(rewind to)到执行main函数时的情况,也就是抛弃了cmd_add和do_line的栈帧(见图7-5)。调用longjmp造成main中setjmp的返回,但是,这一次的返回值是1(longjmp的第二个参数)。

<setjmp.h> f1(, , , f2( = = = = = (setjmp(jmpbuffer) != = = = = = i, j, k,

如果以不带优化和带优化选项对此程序分别进行编译,然后运行它们,则得到的结果是不同的:

[root@localhost apue]# cc -o prog7- prog7-/prog7-
= , autoval = , regival = ,volaval = , statval = = , autoval = , regival = ,volaval = , statval = -o prog7- -O prog7-/prog7-
= , autoval = , regival = ,volaval = , statval = = , autoval = , regival = ,volaval = , statval = 

注意,全局、静态和易失变量不受优化的影响,在调用longjmp后,它们的值是最近所呈现的值。

某个系统的setjmp(3)手册页上说明,存放在存储器中的变量将具有longjmp时的值,而在CPU和浮点寄存器中的变量则恢复为调用setjmp时的值。

不进行优化时,所有这5个变量都存放在存储器中(亦即忽略了对regival变量的register存储类说明)。而进行了优化后,autoval和regival都存放在寄存器中(即使autoval并未声明为register),volatile变量则仍存放在存储器中。

通过这一实例我们可以理解到,如果要编写一个使用非局部跳转的可移植程序,则必须使用volatile属性。

2、自动变量的潜在问题

基本规则是声明自动变量的函数已经返回后,不能再引用这些自动变量。

本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/

相关内容