代码之家  ›  专栏  ›  技术社区  ›  Curd

setjmp/longjmp和局部变量

c
  •  22
  • Curd  · 技术社区  · 15 年前

    我的问题是关于局部变量的setjmp/longjmp的行为。

    jmp_buf env;
    
    
    void abc()
    {
      int error;
    
      ... 
      if(error)
        longjmp(env);
    }
    
    
    void xyz() {
      int v1;           // non-volatile; changed between setjmp and longjmp
      int v2;           // non-volatile; not changed between setjmp and longjmp
      volatile int v3;  // volatile;     changed between setjmp and longjmp
      volatile int v4;  // volatile;     not changed between setjmp and longjmp 
    
      ...
    
      if(setjmp(env)) {
        // error handling
        ...
        return;
      }
    
      v1++; // change v1
      v3++; // change v3
    
      abc();
    }
    
    
    int main(...) {
      xyz();
    }
    

    setjmp/longjmp的文档说明:

    “在调用longjmp()时,所有可访问对象都有值, 除了自动存储持续时间的对象的值 是包含相应函数调用的函数的本地 setjmp()没有volatile限定类型且已更改

    我看到以下两种可能的解释:

    说明1:

    • 非挥发性和

    说明2:

    局部变量被还原,除了

    • 那些改变了的

    根据longjmp之后的解释1,只有v1未定义。定义了v2、v3、v4。 根据longjmp之后的解释2,仅定义了v4。v1、v2、v3未定义。

    2 回复  |  直到 15 年前
        1
  •  31
  •   Nubok eQ19    8 年前

    setjmp/longjmp是通过在第一次传递时保存寄存器(包括堆栈和代码指针等)并在跳转时恢复它们来实现的。

    非“易失性”的自动(也称为“本地”,堆栈分配)变量 也许

    在这些情况下,longjmp将把这些寄存器变量恢复为第一次调用setjmp()时的值。

    此外,一个特别聪明的编译器可能会避免从另一个变量的状态推断出的变量,并根据需要计算它们。

    Volatile显式告诉编译器不要将变量存储在寄存器中。

        2
  •  16
  •   caf    15 年前

    解释1是正确的。如果解释2是有意的,原文将使用“