10

我已经读过 setjmp 在传入的 jmp_buf 变量中“保存程序状态”,但我还没有找到任何关于它的确切含义的描述。它是否会复制所有应用程序的内存?只是寄存器?堆栈?

4

4 回答 4

5

以下内容来自Peter Prinz 和 Tony Crawford 的C in a Nutshell

宏将setjmp()调用时的当前环境保存在其参数指定的缓冲区中。环境包括堆栈,以及所有具有自动存储持续时间的变量。

以下是ISO/IEC 9899:TC2在第 7.13 节中所说的内容:

调用setjmp宏的环境包含足以调用longjmp函数以将执行返回到正确块和调用该块的信息,如果它被递归调用的话。它不包括浮点状态标志、打开文件或抽象机的任何其他组件的状态。

这是 PJ Plauger 在他的书《标准 C 库》中的一个有趣的参考:

[实现 setjmp] 的危险之一在于表达式评估。典型的计算机有一些寄存器,用于在计算表达式时保存中间结果。但是,编写一个足够复杂的表达式,您可能会耗尽可用的寄存器......必须猜测要在数据对象setjmp中存储多少“调用上下文” 。jmp_buf可以肯定的是,必须保存某些寄存器。

最后,来自Peter Van Der Linden 的Expert C Programming

Setjmp 将程序计数器的副本和当前指针保存到堆栈顶部。

根据上述信息,在我看来,“当前环境”是由实施决定的。

于 2014-08-12T15:29:25.470 回答
4

根据平台 ABI,它只是需要在函数调用中保留的寄存器。

来源:在各种操作系统上反汇编x86、x64、arm32、arm64上的setjmp。

于 2014-08-12T14:27:24.317 回答
1

setjmp() 函数保存大多数通用寄存器的内容,就像它们保存在任何函数条目中一样。它还保存堆栈指针和返回地址。所有这些都放在缓冲区中。然后它安排函数返回零。

longjmp() 函数恢复通用寄存器和堆栈指针,然后跳转到先前保存的返回地址。在实践中,它可以显式地执行此操作,或者通过设置堆栈并执行正常的函数返回来执行此操作。在这种情况下,该函数返回一个非零值。

原理是一样的,但是在我遇到的许多不同的 CPU 中,细节差异很大。

于 2014-08-12T14:59:46.467 回答
1

从 setjmp 手册页

   setjmp()  and  longjmp(3)  are  useful for dealing with errors and interrupts encountered in a
   low-level subroutine of a program.  setjmp() saves the stack context/environment  in  env  for
   later  use  by longjmp(3).  The stack context will be invalidated if the function which called
   setjmp() returns.

本质上,它会记住当前堆栈位置和寄存器状态。当您调用 longjmp 时,您会跳回到相同的程序计数器和堆栈位置,并恢复一些额外的寄存器。

这些通常被称为“非本地 goto”。它们不像会复制内存状态或类似的东西的叉子。

于 2014-08-12T14:29:00.240 回答