c++异常管理(二)---setjmp、longjmp与自动变量
2015-07-07 10:34
316 查看
首先上代码:
首先我们要搞清楚各种变量的存放位置:
自动变量: 保存在栈中
静态变量: 静态局部变量,静态全局变量。保存在 bss 或者 data 段
寄存器变量: 推荐在寄存器中进行访问。
volatile 变量; 易失去的变量。 对此变量的访问需要对内存进行读取, 与编译器优化无关。
编译程序的时候不进行任何的优化:
[root@centos C]# gcc setlongjmp.c -o setlongjmp [root@centos C]#
./setlongjmp in f1(): globval = 95, autuval = 96, regival = 97,
volaval = 98, statval = 99 after longjmp: globval = 95, autoval = 96,
regival = 97, volaval = 98, statval = 99
如果是待优化的编译:
[root@centos C]# ./setlongjmp in f1(): globval = 95, autuval = 96,
regival = 97, volaval = 98, statval = 99 after longjmp: globval = 95,
autoval = 2, regival = 3, volaval = 98, statval = 99
我们可以看到
从经过优化后的代码输出可见,autoval 和 regival 这两个变量(前者是自动变量,后者是寄存器变量)的的值回滚为 main 中的初值 2 和 3 。
原因是: autoval 与 regival 本质上还是局部变量,在进行优化的时候直接采用 autoval 和 regival的操作是利用立即数来操作的,也就是说在编译器完可执行文件之后,autoval 与 regival 两个值 就以立即数存在于可执行文件了。
不带优化的代码两次的输出的结果都一样,其原因是因为不优化,所以不追求执行的效率和速度,因此各个变量的读取和写入都是老老实实的通过操作内存中的栈来进行的。
需要注意的是,全局变量,静态变量以及易失变量它们是不受优化影响的。全局变量有全局变量的存储空间,静态变量有静态变量的存储空间,易失变量它虽然没有自己特定的空间,但它不接受优化,所以它不会像上面那样和自动变量,寄存器变量被优化成“立即数”,它仍然是老老实实的入栈出栈。
结论:
所以,当我们编写一个使用非局部跳转(使用 longjmp 的跳转)的可移植程序时,必须考虑使用 volatile 属性,否贼从一个系统移植到另一个系统时,不能保证你还是原来的你,甚至是面目全非。
#include <stdio.h> #include <stdlib.h> #include <setjmp.h> staticvoid f1(int,int,int,int); staticvoid f2(void); staticjmp_buf jmpbuffer; staticint globval; //静态全局变量,保存在bss或者data段 intmain(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); } globval = 95; autoval = 96; regival = 97; volaval = 98; statval = 99; f1(autoval, regival, volaval, statval); exit(0); } staticvoid f1(inti, intj, intk, intl) { printf("in f1():\n"); printf("globval = %d, autoval = %d, regival = %d, volaval = %d, statval = %d\n", globval, i, j, k, l); f2(); } staticvoid f2(void) { longjmp(jmpbuffer, 1); }
首先我们要搞清楚各种变量的存放位置:
自动变量: 保存在栈中
静态变量: 静态局部变量,静态全局变量。保存在 bss 或者 data 段
寄存器变量: 推荐在寄存器中进行访问。
volatile 变量; 易失去的变量。 对此变量的访问需要对内存进行读取, 与编译器优化无关。
编译程序的时候不进行任何的优化:
[root@centos C]# gcc setlongjmp.c -o setlongjmp [root@centos C]#
./setlongjmp in f1(): globval = 95, autuval = 96, regival = 97,
volaval = 98, statval = 99 after longjmp: globval = 95, autoval = 96,
regival = 97, volaval = 98, statval = 99
如果是待优化的编译:
[root@centos C]# ./setlongjmp in f1(): globval = 95, autuval = 96,
regival = 97, volaval = 98, statval = 99 after longjmp: globval = 95,
autoval = 2, regival = 3, volaval = 98, statval = 99
我们可以看到
从经过优化后的代码输出可见,autoval 和 regival 这两个变量(前者是自动变量,后者是寄存器变量)的的值回滚为 main 中的初值 2 和 3 。
原因是: autoval 与 regival 本质上还是局部变量,在进行优化的时候直接采用 autoval 和 regival的操作是利用立即数来操作的,也就是说在编译器完可执行文件之后,autoval 与 regival 两个值 就以立即数存在于可执行文件了。
不带优化的代码两次的输出的结果都一样,其原因是因为不优化,所以不追求执行的效率和速度,因此各个变量的读取和写入都是老老实实的通过操作内存中的栈来进行的。
需要注意的是,全局变量,静态变量以及易失变量它们是不受优化影响的。全局变量有全局变量的存储空间,静态变量有静态变量的存储空间,易失变量它虽然没有自己特定的空间,但它不接受优化,所以它不会像上面那样和自动变量,寄存器变量被优化成“立即数”,它仍然是老老实实的入栈出栈。
结论:
所以,当我们编写一个使用非局部跳转(使用 longjmp 的跳转)的可移植程序时,必须考虑使用 volatile 属性,否贼从一个系统移植到另一个系统时,不能保证你还是原来的你,甚至是面目全非。
相关文章推荐
- 10行代码编写一个c++服务器
- nyoj阶乘分解因式(1)
- 关于C++builder中精度丢失的问题
- C++读取特定路径下文件目录及文件名称&&文件结构
- 最大子序列和
- 黑马程序员——C/OC—OC对比C语言的差异化
- C语言实现双链表基本操作(创建、查找、插入、删除)
- chapter16test6
- C语言学习笔记:18_数组-二维数组
- 默认实参需要注意的几个地方
- C语言学习笔记:17_数组-一维数组(基本操作,选择和冒泡排序,斐波那契数列)
- C++知识点随笔(三):static、const、friend、inline
- C#调用C/C++动态库 封送结构体,结构体数组
- C++异常系列(一)----setjmp 与 longjmp
- C++ 大规模程序设计 之 物理层次结构
- C语言语法部分
- C++学习-派生类的复制运算符
- 基于C语言sprintf函数的深入理解
- c++ 简单的异常
- C++中各种<string,T>关联方式的速度对比