zoukankan      html  css  js  c++  java
  • 学习之"setjmp和longjmp函数"

    Linux学习之"setjmp和longjmp函数"

     

     转贴,原文地址:http://www.cnblogs.com/lq0729/archive/2011/10/23/2222117.html

    nsetjmp和longjmp函数实现函数之间的跳转(需包含头文件"setjmp.h"):
    函数原型:int setjmp(jmp_buf env);
          void longjmp(jmp_buf env, int val);
    setjmp函数用于设置跳转的目的位置,longjmp函数进行跳转。
    env:保留了需要返回的位置的堆栈情况。
    setjmp的返回值:直接调用该函数,则返回0;若由longjmp的调用,导致setjmp被调用,则返回val(longjmp的第二个参数)。
    1.longjmp对各类型参数的影响:
    考虑下面这个程序:
     1 #include<iostream>
     2 #include<setjmp.h>
     3 #include<stdlib.h>
     4 #include<stdio.h>
     5 
     6 using namespace std;
     7 
     8 jmp_buf jmpbuffer;
     9 
    10 void g()
    11 {
    12   cout << "in g()" << endl;
    13 
    14   longjmp(jmpbuffer, 2);
    15 }
    16 
    17 void f()
    18 {
    19   cout << "in f()" << endl;
    20 
    21   g();
    22 
    23   cout << "leave f()" << endl;
    24 }
    25 
    26 int globval;
    27 
    28 int main()
    29 {
    30   int autoval;
    31   register int regival;
    32   volatile int volaval;
    33   static int statval;  
    34 
    35   cout << "begin" << endl;
    36 
    37   globval = 90;
    38   autoval = 91;
    39   regival = 92;
    40   volaval = 93;
    41   statval = 94;
    42   
    43   int i = setjmp(jmpbuffer);
    44 
    45   cout << "setjmp return code: " << i << endl;
    46 
    47   if(2 == i)
    48   {
    49     cout << "error code: "<< i << endl;
    50 
    51     cout << "globval= " << globval << "; ";
    52     cout << "autoval= " << autoval << "; ";
    53     cout << "regival= " << regival << "; ";
    54     cout << "volaval= " << volaval << "; ";
    55     cout << "statval= " << statval << "; " << endl;
    56     return 0;
    57   }
    58 
    59   globval = 0;
    60   autoval = 1;
    61   regival = 2;
    62   volaval = 3;
    63   statval = 4;
    64 
    65   cout << "globval= " << globval << "; ";
    66   cout << "autoval= " << autoval << "; ";
    67   cout << "regival= " << regival << "; ";
    68   cout << "volaval= " << volaval << "; ";
    69   cout << "statval= " << statval << "; " << endl;
    70 
    71   f();  
    72 
    73   return 0;
    74 }
    View Code
    在编译时禁止优化,输出结果如下:

    使用O3优化编译,结果如下:

    在非优化时,包括寄存器变量(register修饰)在内的所有类型都被存放在内存中,所以所有变量都是更改后的值。

    在优化编译时,自动变量(默认类型)和寄存器变量被存储在寄存器中,其它变量与非优化时一样。所以autoval和regival都还原为原来的值。

    附jmp_buf结构:

    §
    复制代码
    typedef struct
    {
    unsigned j_sp; // 堆栈指针寄存器
    unsigned j_ss; // 堆栈段
    unsigned j_flag; // 标志寄存器
    unsigned j_cs; // 代码段
    unsigned j_ip; // 指令指针寄存器
    unsigned j_bp; // 基址指针
    unsigned j_di; // 目的指针
    unsigned j_es; // 附加段
    unsigned j_si; // 源变址
    unsigned j_ds; // 数据段
    } jmp_buf;
    复制代码

    保证局部变量在longjmp过程中一直保存它的值的方法:把它声明为volatile变量。(适合那些在setjmp执行和longjmp返回之间会改变的变量)。
    存放在内存中的变量,将具有调用longjmp时的值,而在CPU和浮点寄存器中的变量则恢复为调用setjmp函数时的值。
    优化编译时,register和auto变量都存放在寄存器中,而volatile变量仍存放在内存。
  • 相关阅读:
    关于在MAC上进行 LARAVEL 环境 Homestead 安装过程记录
    js 贷款计算器
    js 实现阶乘
    js 两点间距离函数
    composer Your requirements could not be resolved to an installable set of packages
    vue 项目优化记录 持续更新...
    vue 项目打包
    vue 真机调试页面出现空白
    vue 真机调试
    谈谈-Android状态栏的编辑
  • 原文地址:https://www.cnblogs.com/ysmintor/p/4356775.html
Copyright © 2011-2022 走看看