Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C setjmp/longjmp和局部变量_C - Fatal编程技术网

C setjmp/longjmp和局部变量

C setjmp/longjmp和局部变量,c,C,我的问题是关于局部变量的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 chang

我的问题是关于局部变量的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。 根据longjmp之后的解释2,仅定义了v4。v1、v2、v3未定义

哪一个是对的


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

解释1是正确的。如果解释2是预期的,原始文本将使用“,它们将被更改”而不是“和”。

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

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

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

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

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

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


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

实现注意:更改且非可变的变量可能与longjmp时相同,或者可以恢复到setjmp时的状态,具体取决于代码生成。因此“不确定”。因此,如果没有更改,这两个值是相同的,这就是为什么未更改的变量是安全的。我猜相反,声明为“register”的自动变量可能存储在寄存器中,但编译器可能会忽略提示,所以这也不能保证它们会被恢复。@Michael实际上甚至不能保证任何东西都会被“恢复”。“正常”情况是,在调用导致longjmp的任何函数之前,变量将具有它们的值。在上述某些情况下,setjmp/longjmp对所有保存调用的寄存器进行盲恢复可能会“破坏”它们。实际上,这意味着,如果被删除,它们可能会恢复为“setjmp”值,但该语言只声明它们是不确定的,而不是您上次设置它们的值。