这个setjmp/longjmp上下文中的自动变量是什么?

Joh*_*0te 9 c unix

UNIX环境中的高级编程由W. Richard Stevens指出:

"主函数中自动变量和寄存器变量的状态是什么?"

关于当你longjmp从堆栈下面的某个地方回到main(或另一个函数)时会发生什么.

它继续说:

"这取决于.大多数实现不会尝试回滚这些自动变量并注册变量,但标准所说的都是它们的值是不确定的.如果你有一个你不想回滚的自动变量,用它来定义它在 volatile当被声明全局或静态属性.变量单独留在家中longjmp被执行.

看起来他说正常的堆栈变量不会将它们的值设置回setjmp时的值 - 但是在longjmp返回之后,函数的其余部分不能依赖于它的堆栈变量.看起来很疯狂,所以我猜我错了.

有人可以为我定义"自动变量"并解释具体没有恢复到原始值的原因以及为什么会这样?

NPE*_*NPE 6

它只是说,如果

  1. 你有一个未声明的自动(函数本地非静态)变量volatile; 和
  2. 你在setjmp和之间改变变量的值longjmp

然后在该longjmp变量的值变得不确定之后.

我认为这与这些变量驻留在CPU寄存器而不是RAM中的可能性有关,以及相关的难以保留这些变量的值longjmp.

以下是gcc手册中的引用:

如果使用longjmp,请注意自动变量.ISO C表示未声明的自动变量volatile在a之后具有未定义的值longjmp.这是GCC所做的所有承诺,因为正确恢复寄存器变量非常困难,GCC的一个特点是它可以将变量放入寄存器而不需要它.

如果变量值的潜在丢失在您的用例中是一个问题,请将相关变量声明为volatile.

  • 当然,那个gcc手册是一个很糟糕的解释:这实际上并不是ISO C所说的.它只是使它未定义_如果它们被修改_,并且难以恢复它们(毕竟,你可以保存和恢复所有寄存器)但是_avoiding_不需要的恢复. (3认同)

Ran*_*832 6

"自动变量"是普通(未用寄存器或静态声明)局部变量的旧术语,它可以追溯到C标准中使用的术语和auto关键字的原始含义.见标准的 6.2.4和6.7.1节

至于这个:

但是在longjmp回到它之后,函数的其余部分不能依赖于它的堆栈变量,这似乎很疯狂

这个想法是,如果你要去longjmp,你不应该首先修改它们,因为那样你就不知道会发生什么.

原因是,longjmp的可能恢复状态,例如处理器寄存器,其中的自动变量可能已被映射到(有没有保证,他们将在"堆栈",或在内存中.即使在内存中不存在的话,某些操作可能不会[除非它被声明为volatile]直接访问内存但可以访问已经加载了值的处理器寄存器)

你的问题有点奇怪,因为它意味着你会希望它们被恢复[即你要修改的干预功能] - 一般来说,这个警告是警告它们可能会在不期望时被意外恢复."未恢复"并不意味着"无法使用"[虽然标准DOES声明它们不可用,因为它可能会恢复缓存的寄存器而不是内存,因此您将获得不一致的结果],这意味着"具有后续函数写入的值它(因为你传递了打算写入的地址)".