先来看个实例吧,在 用c++写的简易学生通讯录中有那么个实例:删除通讯录中某个人的号码;1、开始是主页面菜单函数,选择删除功能后;2、跳转到删除信息函数中,在这个函数中还要先调用查找函数;3、在查找函数中又要判断以什么方式查找(姓名还是学号);4、选择好查找方式以后,查找到该人信息返回;5、打印信息再次确认是否真的需要删除这些信息;6、删除后返回到主页面菜单函数;
一个删除功能嵌套调用了这么多函数,假如在某个函数中出错了(或者我在第5步取消删除),又要一层层的返回。幸好Linux中提供了setjmp()和longjmp()函数,用来在函数间进行跳转的,这个跳转是没有返回的是重新跳转到设置点处;
请看下面的实例:
#include
#include//主要为了提供exit()函数
#include//提供setjmp()和longjmp()函数以及jmp_buf数组类型
jmp_buf buffer;//存放当前状态的数组类型
static int global_static_a = 1;
int global_a = 2;
void test2()
{
longjmp(buffer, 2);
}
void test1(int a, int b, int c, int d, int e, int f, int g)
{
printf("\nin test1:\n");
printf("global_static_a = %d\n", a);
printf("global_a = %d\n", b);
printf("auto_a = %d\n", c);
printf("register_a = %d\n", d);
printf("volatile_a = %d\n", e);
printf("static_a = %d\n", f);
if (2 == g)
longjmp(buffer, 1);
test2();
}
int main(int argc, char* argv[])
{
int ret;
int auto_a = 3;
register int register_a = 4;
volatile int volatile_a = 5;
static int static_a = 6;
if (1 == (ret = setjmp(buffer)))
{
printf("\nsetjmp test1:\n");
printf("global_static_a = %d\n", global_static_a);
printf("global_a = %d\n", global_a);
printf("auto_a = %d\n", auto_a);
printf("register_a = %d\n", register_a);
printf("volatile_a = %d\n", volatile_a);
printf("static_a = %d\n", static_a);
exit(0);
}else if ( 2 == ret)
{
printf("\nsetjmp test2:\n");
return 0;
}else;
global_static_a *= 10;
global_a *= 10;
auto_a *= 10;
register_a *= 10;
volatile_a *= 10;
static_a *= 10;
test1(global_static_a, global_a, auto_a, register_a, volatile_a, static_a, argc);
return 0;
}
上面的流程比较简单:主函数 ==》 test1() ==》 test2();为了显示能在多处地方设置跳转点,这里用了命令行参数。如果有2个参数,则在test1()中就跳转回去;否则在test2()函数中跳转;
大概分析下这两个跳转函数的本质关系:
longjmp()调用之前 longjmp()调用之后
栈的底部 ---------------------- 高地址 栈的底部 -------------------- 高地址
| main()的栈 | | main()的栈 |
---------------------- --------------------
| test1()的栈 | | 空栈 | 跳转后释放了test1()的栈空间
---------------------- ---------------------
| test2(0的栈 | | 空栈 | 跳转后释放了test2()的栈空间
---------------------- ---------------------
栈的顶部 | | 低地址 | |
由上面的栈结构可以知道,longjmp()函数调用之后,其实质就是用esp回退到main函数中,清空掉test1() 和test2()的堆栈空间。
未优化的结果:
优化后的结果:
根据两种结果可以知道寄存器变量和自动变量回退回去时,优化后得到的是个不确定的值;
转载请注明作者和原文出处,原文地址:http://blog.csdn.net/yuzhihui_no1/article/details/43983809
若有不正确之处,望大家指正,共同学习!谢谢!!!