先来看个实例吧,在 用c++写的简易学生通讯录中有那么个实例:删除通讯录中某个人的号码;1、开始是主页面菜单函数,选择删除功能后;2、跳转到删除信息函数中,在这个函数中还要先调用查找函数;3、在查找函数中又要判断以什么方式查找(姓名还是学号);4、选择好查找方式以后,查找到该人信息返回;5、打印信息再次确认是否真的需要删除这些信息;6、删除后返回到主页面菜单函数;
一个删除功能嵌套调用了这么多函数,假如在某个函数中出错了(或者我在第5步取消删除),又要一层层的返回。幸好Linux中提供了setjmp()和longjmp()函数,用来在函数间进行跳转的,这个跳转是没有返回的是重新跳转到设置点处;
请看下面的实例:
#include<stdio.h> #include<stdlib.h>//主要为了提供exit()函数 #include<setjmp.h>//提供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
若有不正确之处,望大家指正,共同学习!谢谢!!!