繁体   English   中英

setjmp / longjmp和局部变量

[英]setjmp/longjmp and local variables

我的问题针对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限定类型,并且在setjmp()调用和longjmp()调用之间更改的变量是不确定的。”

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

解释1:

恢复局部变量,但同时包含的变量除外

  • 非易失性的
  • 变了

解释2:

恢复本地变量,除了

  • 那些是非易失性的
  • 那些改变的

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

哪一个是对的?

顺便说一句:我需要一个对所有编译器都有效的通用(“便携式”)答案,即尝试使用一个特定的编译器没有帮助。

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

自动(又名“本地”,堆栈分配)变量不是“挥发” 可以存储在寄存器中,而不是在堆栈上。

在这种情况下,longjmp将在首次调用setjmp()时将这些寄存器变量恢复为其值。

此外,特别聪明的编译器可能会避免从其他变量的状态推断出的变量,并根据需要进行计算。

但是,如果变量是自动的但未分配寄存器,则可以通过setjmp和longjmp之间的代码对其进行更改。

易失性明确地告诉编译器不要将变量存储在寄存器中。

因此,除非您明确声明变量是可变变量,否则如果在setjmp / longjmp之间更改了变量,则变量的值将取决于编译器所做的选择,因此,您不应依赖它(“不确定”)。

解释1是正确的。 如果要使用解释2,则原始文本将使用“ 已更改”而不是“和”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM