[英]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.