我已经读过setjmp“将程序状态保存在传入的jmp_buf变量中”,但是我还没有找到任何关于它究竟是什么的描述。它是否复制了所有应用程序的内存?只是寄存器?堆栈?
答案 0 :(得分:4)
以下内容来自Peter Prinz和Tony Crawford的 C in a Nutshell :
setjmp()
宏将调用时的当前环境保存在其参数指定的缓冲区中。环境包括堆栈,以及具有自动存储持续时间的所有变量。
以下是 ISO / IEC 9899:TC2 在第7.13节中所说的内容:
调用
setjmp
宏的环境包含足以调用longjmp
函数以将执行返回到正确的块并调用该块的信息,如果它是递归调用的。它不包括浮点状态标志,打开文件或抽象机器的任何其他组件的状态。
以下是P.J. Plauger在他的书 The Standard C Library 中的有趣参考:
实施setjmp的一个危险在于表达式评估。典型的计算机具有一定数量的寄存器,用于在评估表达式时保存中间结果。但是,写一个足够复杂的表达式,你可能会耗尽可用的寄存器......
setjmp
必须猜测存储在jmp_buf
数据对象中的“调用上下文”的数量。可以肯定的是,必须保存某些寄存器。
最后,来自Peter Van Der Linden的 Expert C Programming 。
Setjmp将程序计数器的副本和当前指针保存到堆栈顶部。
根据以上信息,我认为“当前环境”需要实施。
答案 1 :(得分:3)
根据平台ABI,它只是需要在函数调用中保留的寄存器。
来源:在各种操作系统上对x86,x64,arm32,arm64上的setjmp进行反汇编。
答案 2 :(得分:1)
setjmp()函数保存大多数通用寄存器的内容,其保存方式与保存在任何函数条目中的方式相同。它还保存堆栈指针和返回地址。所有这些都放在缓冲区中。然后它安排函数返回零。
longjmp()函数恢复通用寄存器和堆栈指针,然后跳转到先前保存的返回地址。在实践中,它可以显式地执行此操作,或者通过设置堆栈并执行正常的函数返回。在这种情况下,该函数返回一个非零值。
原理是一样的,但在我遇到的许多不同的CPU中,细节有很大不同。
答案 3 :(得分:0)
来自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时,你会跳回到相同的程序计数器和堆栈位置,并恢复一些额外的寄存器。
这些通常被称为“非本地的”。它们不像是一个可以复制内存状态或类似内容的分支。