关闭

c++异常管理(二)---setjmp、longjmp与自动变量

165人阅读 评论(0) 收藏 举报
分类:

首先上代码:

#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);
}

首先我们要搞清楚各种变量的存放位置:

  1. 自动变量: 保存在栈中
  2. 静态变量: 静态局部变量,静态全局变量。保存在 bss 或者 data 段
  3. 寄存器变量: 推荐在寄存器中进行访问。
  4. 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 属性,否贼从一个系统移植到另一个系统时,不能保证你还是原来的你,甚至是面目全非。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:31059次
    • 积分:887
    • 等级:
    • 排名:千里之外
    • 原创:54篇
    • 转载:12篇
    • 译文:4篇
    • 评论:0条
    文章分类