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

原创 2015年07月07日 10:34:03

首先上代码:

#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 属性,否贼从一个系统移植到另一个系统时,不能保证你还是原来的你,甚至是面目全非。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

C++变量的存储类别(动态存储、静态存储、自动变量、寄存器变量)

一、动态存储方式与静态存储方式 上一节已介绍了变量的一种属性——作用域,作用域是从空间的角度来分析的,分为全局变量和局部变量。 变量还有另一种属性——存储期(storage duration,也称...
  • tdmyl
  • tdmyl
  • 2013-09-12 19:08
  • 526

C++变量的存储类别(动态存储、静态存储、自动变量、寄存器变量、外部变量)

动态存储方式与静态存储方式 我们已经了解了变量的作用域。作用域是从空间的角度来分析的,分为全局变量和局部变量。   变量还有另一种属性——存储期(storage duration,也称生命期)。...

c语言 异常捕捉 setjmp & longjmp

此文是学习 C专家编程 中的笔记。 setjmp和longjmp是C语言所独有的,它们部分弥补了C语言有限的转移能力。 函数说明(来自wiki百科): int setjmp(jmp_...

C语言中利用setjmp和longjmp做异常处理

错误处理是任何语言都需要解决的问题,只有不能保证100%的正确运行,就需要有处理错误的机制。异常处理就是其中的一种错误处理方式。 1 过程活动记录(Active Record) C语言中每...

C语言 控制转移 异常处理机制 setjmp & longjmp

C语言中有一个goto语句,其可以结合标号实现函数内部的任意跳转(通常情况下,很多人都建议不要使用goto语句,因为采用goto语句后,代码维护工作量加大)。另外,C语言标准中还提供一种非局部跳转“n...

C语言中一种更优雅的异常处理机制 - setjmp/longjmp

转自:http://blog.chinaunix.net/u/22711/showart_445098.html 实际上goto语句是面向过程与面向结构化程序语言中,进行异常处理编程的最原始的支...

C语言异常处理机制, setjmp() and longjmp()

1、什么是异常    异常一般指的是程序运行期(Run-Time)发生的非正常情况。    异常一般是不可预测的,如:内存不足、打开文件失败、范围溢出等。    UNIX 使用信号给出异常,并当...

C异常处理机制:setjmp和longjmp

setjmp()和longjum()是通过操纵过程活动记录实现的。它是C语言所独有的。它们部分你不了C语言有限的转移能力。这个两个函数协同工作,如下所示:     *setjmp(jmp_buf j...

详解C的异常处理机制(goto\setjmp longjmp)

来自希赛网,作者王胜祥。 1 C语言中的异常处理机制     在这之前的所有文章中,都是阐述关于C++的异常处理机制。的确,在C++语言中,它提供的异常处理的模型是非常完善的,主人公阿愚因此才和“...

C异常处理机制:setjmp和longjmp

setjmp.h is a header defined in the C standard library to provide "non-local jumps": control flow th...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)