首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >setjmp/longjmp和局部变量

setjmp/longjmp和局部变量
EN

Stack Overflow用户
提问于 2009-09-08 11:21:11
回答 2查看 8.3K关注 0票数 30

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

示例代码:

代码语言:javascript
复制
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()调用的函数的本地值,这些对象不具有易失性限定类型,并且在setjmp()调用和longjmp()调用之间进行更改。”

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

intepretation1:

将恢复局部变量,但两个变量都还原的变量除外。

  • changed

  • 非易失性

intepretation2:

恢复局部变量,但

  • 是非易失性的,
  • 是改变

的。

根据interpretation1的说法,只有v1是未定义的。定义了v2,v3,v4。根据interpretation2,在longjmp之后只定义了v4。v1,v2,v3是未定义的。

哪一个是对的?

顺便说一句:我需要一个对所有编译器都有效的通用(“可移植”)答案,也就是说,用一个特定的编译器进行测试是没有帮助的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-09-08 11:29:26

解释1是正确的。如果解释2是有意的,那么原文将使用“”而不是"and“。

票数 16
EN

Stack Overflow用户

发布于 2009-09-08 11:29:38

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

非“易失性”的自动(也称为“本地”,堆栈分配)变量可以存储在寄存器中而不是堆栈上。

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

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

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

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

因此,除非显式地说变量是易失性的,否则如果在setjmp/longjmp之间更改变量,它的值将取决于编译器所做的选择,因此不应该依赖(‘不确定性’)。

票数 34
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1393443

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档