首页 > 解决方案 > 是否允许一次 setjmp() 调用多次执行 longjmp() ?

问题描述

setjmp()在我的理解中, and的一个典型用法longjmp()是异常处理(in 的用法libpng应该是一个著名的例子),最多只有longjmp()一次setjmp()调用。

这样的一个电话是否可以安全地longjmp()多次执行setjmp()

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

jmp_buf jb;
int i;

int main(void) {
    i = 0;
    setjmp(jb);
    printf("%d\n", i);
    i++;
    if (i < 10) longjmp(jb, 1);
    return 0;
}

输出

0
1
2
3
4
5
6
7
8
9

我成功地从这次执行中得到了预期的输出,但这能保证吗?或者一旦用于那个jmp_buf时候就会失效?longjmp()

setcontext - 维基百科说“它们可能被视为 setjmp/longjmp 的高级版本;而后者只允许单个非本地跳转堆栈”,但我没有从N1570longjmp()中找到不允许多次使用这样的描述7.13 非局部跳转<setjmp.h>。

我知道不鼓励使用setjmp()and ,但我想知道在使用循环语句 ( , , )longjmp()时是否可以将它们用作解决方法,并且在某些编程测验中禁止使用and不禁止语句。(使用递归可能是此类测验的答案,但在尝试处理需要多次迭代的大数据时存在堆栈溢出的风险)forwhiledo-whilegotosetjmp()longjmp()

标签: clanguage-lawyersetjmp

解决方案


对于这样的一个 setjmp() 调用,是否可以安全地多次执行 longjmp() ?

可以构造一个严格遵从的程序,longjmp()多次调用以返回到同一个setjmp()调用点。它归结为抽象机器的状态,包括内存内容,尤其是jmp_buf调用setjmp()记录返回调用点所需的状态的状态。该标准规定

所有可访问的对象都有值,抽象机器的所有其他组件都有状态,截至longjmp函数被调用时,除了[...可以避免或无关紧要的细节...]。

(C2018 7.13.2.1/3)

特别是,这意味着longjmp()调用不能更改jmp_buf它从中获取信息的值,并且其他地方不能有任何隐藏状态longjmp()可以更新以将相应的标记setjmp()为已用完。如果机器状态允许符合要求的调用,则在相应调用的结果第二个(或第三个)返回之后longjmp(),等效longjmp()调用必须仍然符合要求。setjmp()


推荐阅读