在包装函数和局部变量破坏中使用 setjmp

Using setjmp in a wrapper function and local variable clobbering

联机帮助页(在我的系统上)中的 setjmp(3) 文档指出

All accessible objects have values as of the time longjmp() routine was called, except that the values of objects of automatic storage invocation duration that do not have the volatile type and have been changed between the setjmp() invocation and longjmp() call are indeterminate.

这是否仅包括与调用 setjmp 的函数处于同一范围内的对象,或者还包括调用堆栈上层函数范围内的任何对象?

例如,下面的代码是否正确?

#include <stdio.h>
#include <setjmp.h>

jmp_buf env;

void function_that_longjmps(void)
{
    longjmp(env, 1);
}

int setjmp_wrapper(jmp_buf env)
{
    if (setjmp(env) == 0)
        return 0;
    else
        return 1;
}

int main()
{
    int i = 0;

    if (setjmp_wrapper(env) == 0) {
        i = 1;
        function_that_longjmps();
    }

    printf("i = %d\n", i);
    return 0;
}

局部变量 isetjmplongjmp 调用之间被修改,但它不存在于 setjmp_wrapper 的范围内。在这种情况下,变量是否有可能被破坏?

无论局部变量发生什么情况,您的示例都表现出未定义的行为,因为您无法 longjmp 进入已经返回的函数执行。

至于没有表现出UB的例子,也许

#include <stdio.h>
#include <setjmp.h>

jmp_buf env;

void calls_longjmp(int *p) {
    *p = 1;
    longjmp(env);
}
void calls_setjmp(int *p) {
    if (setjmp(env)) {
        return;
    }
    calls_longjmp(p);
}
int main(void) {
    int x = 0;
    calls_setjmp(&x);
    printf("%d\n", x);
}

那么 xlongjmp 之后保证有值 1,而不是 0 或不确定。引用 C11 N1570 draft:

All accessible objects have values, and all other components of the abstract machine249) have state, as of the time the longjmp function was called, except that the values of objects of automatic storage duration that are local to the function containing the invocation of the corresponding setjmp macro that do not have volatile-qualified type and have been changed between the setjmp invocation and longjmp call are indeterminate.