zoukankan      html  css  js  c++  java
  • 第5章 进程环境(5)_非局部跳转

    6. 非局部跳转

    (1)setjmp和longjmp语句

    头文件

    #include<setjmp.h>

    函数

    int* setjmp(jum_buf env);

    返回值

    直接调用返回0,若从longjmp调用返回则返回非0值

    功能

    设置非局部跳转的跳转点

     

    函数

    void longjmp(jmp_buf env, int val);

    功能

    进行非局部转转,val为返回值

    参数

    env:一个特殊类型jmp_buf。这一数据类型是某种形式的数组,其中存放在调用longjmp时能用来恢复栈状态的信息(如,各寄存器的值;但不保存线程栈局部变量等数据)。一般,env变量是个全局变量,因为需要从另一个函数引用它。

    备注

    (1)C程序缺乏异常处理方法,可使用非局部跳转处理C程序的异常。

    (2)goto语句仅限于函数内部跳转,而longjmp不限于

    【编程实验】非局部跳转

    //process_jmp.c

    #include <setjmp.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define TOK_ADD      5
    #define TOK_SUB      6
    char* const prompt = "cal: "; //命令行提示符
    
    jmp_buf env;  //保存运行环境,非局部跳转用于函数间的跳转
    
    //命令行格式如:add 3 5  或 sub 5 3
    void do_line(char* line); //解析并执行命令行内容
    void cmd_add(void);
    void cmd_sub(void);
    int get_token(char* line); //从命令行参数中获取标识符
    
    int main(int argc, char* argv[])
    {
        ssize_t size = strlen(prompt) * sizeof(char);
        char buff[256];
        ssize_t len = 0;
    
        //设置跳转点
        if(setjmp(env) < 0){ //直接调用返回0,从longjmp跳转来时,返回longjmp中指定的val值
                             //这里我们设定val为正值,小于0表示setjmp调用失败!
            perror("setjmp error");
            exit(1);
        }
    
        //输出提示符
        write(STDOUT_FILENO, prompt, size);
        while(1)
        {
            len = read(STDIN_FILENO, buff, 256);
            if(len < 0) break;
    
            buff[len -1] = 0;
            do_line(buff);
    
            write(STDOUT_FILENO, prompt, size);
        }
    
        return 0;
    }
    
    
    void do_line(char* line)
    {
        int cmd = get_token(line);
        switch(cmd)
        {
        case TOK_ADD:
            cmd_add();
            break;
        case TOK_SUB:
            cmd_sub();
            break;
        default:
            fprintf(stderr, "error command
    ");
        }
    }
    
    void cmd_add(void)
    {
         int i = get_token(NULL);
         int j = get_token(NULL);
    
         printf("result: %d + %d = %d
    ", i, j, i + j);
    }
    
    void cmd_sub(void)
    {
         int i = get_token(NULL);
         int j = get_token(NULL);
    
         printf("result: %d - %d = %d
    ", i, j, i - j);
    }
    
    static int is_number(char* item)
    {
        int ret = 1;
        int len = strlen(item);
        int i = 0;
        
        for(i=0; i<len; i++) {
            ret = ret  && ('0'<= item[i]) && (item[i] <= '9');
            if (ret == 0) break;
        }
    
        return ret;
    }
    
    int get_token(char* line)
    {
        //格式add 3 4
        //    sub 7 5
        char* item = strtok(line, " ");
        if(line != NULL)
        {
            if(!strcmp("add", item)) return TOK_ADD;
            if(!strcmp("sub", item)) return TOK_SUB;
        }else{
            if(is_number(item)){
                int i = atoi(item);
                return i;
            }else{
                fprintf(stderr, "arg not number
    ");
                longjmp(env, 1);  //1表示跳到跳转点(setjmp)后,setjmp的返回值
            }
        }
    }

    (2)longjmp对各类变量的影响

    变量类型

    受影响情况

    全局变量、静态变量和volatile变量

    不能恢复到原始值

    寄存器变量

    可以恢复到原始值

    自动变量

    优化编译后可能会恢复

      ①存放在存储器中的变量将具有longjmp时的值而在cpu和浮点寄存器中的变量则恢复为调用setjmp时的值

      ②不进行优化时自动变量、寄存器变量、全局变量、静态变量和易失变量等都存放在存储器中(亦即忽略了对reg_var变量的register存储类说明)。

      ③而进行了优化后auto_var和reg_var都存放在寄存器中(即使auto_var并未声明为register),volatile变量则仍存放在存储器中

      ④全局、静态和易失变量不受优化的影响,在调用longjmp后,它们的值是最近所呈现的值。

      ⑤如果要编写一个使用非局部跳转的可移植程序,则必须使用volatile属性

    【编程实验】longjmp对变量的影响

    //longjmp_var.c

    #include <setjmp.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <malloc.h>
    
    int global_var;
    
    jmp_buf env;
    
    int  show(int g_v, int s_v, int a_v, int r_v, int m_v, int v_v);
    int  f1(int g_v, int s_v, int a_v, int r_v, int m_v, int v_v);
    void f2();
    
    int main(int argc, char* argv[])
    {
        static int sta_var;
        int auto_var;
        register reg_var;
        int* heap_var = (int*)malloc(sizeof(int));
        volatile int vola_var;//易失变量
    
        global_var = 1; sta_var = 2; auto_var = 3;
        reg_var = 4; *heap_var = 5; vola_var = 6;
    
        int k = 0;
        if((k = setjmp(env)) < 0 ){
            perror("setjmp error");
        }else if(k == 1){
            printf("after longjmp:
    ");
            show(global_var, sta_var, auto_var, reg_var, *heap_var, vola_var);       
            exit(0);
        }
    
        global_var = 10; sta_var = 20; auto_var = 30;
        reg_var = 40; *heap_var = 50; vola_var = 60;
        
        printf("before longjmp:
    ");
        f1(global_var, sta_var, auto_var, reg_var, *heap_var, vola_var);
     
        return 0;
    }
    
    int  show(int g_v, int s_v, int a_v, int r_v, int m_v, int v_v)
    {
        printf("  global: %d, static: %d, auto: %d, reg: %d, heap: %d vola: %d
    ",
                g_v, s_v, a_v, r_v, m_v, v_v);
    }
    
    int  f1(int g_v, int s_v, int a_v, int r_v, int m_v, int v_v)
    {
        show(g_v, s_v, a_v, r_v, m_v, v_v);
        f2();
    }
    
    void f2()
    {
        longjmp(env, 1);
    }
    /*输出结果:
     [root@bogon 5.process]# gcc -o bin/longjmp_var src/longjmp_var.c
     [root@bogon 5.process]# bin/longjmp_var                         
     before longjmp:
       global: 10, static: 20, auto: 30, reg: 40, heap: 50 vola: 60
     after longjmp:
       global: 10, static: 20, auto: 30, reg: 40, heap: 50 vola: 60
     [root@bogon 5.process]# gcc -O -o bin/longjmp_var src/longjmp_var.c
     [root@bogon 5.process]# bin/longjmp_var                            
     before longjmp:
       global: 10, static: 20, auto: 30, reg: 40, heap: 50 vola: 60
     after longjmp:
       global: 10, static: 20, auto: 3, reg: 4, heap: 50 vola: 60
     */
  • 相关阅读:
    188. Best Time to Buy and Sell Stock IV
    452. Minimum Number of Arrows to Burst Balloons
    435. Non-overlapping Intervals
    28. Implement strStr() KMP
    10. Regular Expression Matching
    877. Stone Game
    格式化日期
    Designer属性编辑器简介
    pandas 根据内容匹配并获取索引
    access 中sql语句之“like” 语句的用法
  • 原文地址:https://www.cnblogs.com/5iedu/p/6354489.html
Copyright © 2011-2022 走看看