简体   繁体   English

究竟什么“程序状态”setjmp保存?

[英]Exactly what “program state” does setjmp save?

I've read that setjmp "saves the program state" in the passed-in jmp_buf variable, but I haven't found any description of exactly what that entails. 我已经读过传入的jmp_buf变量中的setjmp“保存程序状态”,但是我还没有找到任何关于它究竟是什么的描述。 Does it make a copy of all the application's memory? 它是否复制了所有应用程序的内存? Just the registers? 只是寄存器? The stack? 堆栈?

The following is from C in a Nutshell by Peter Prinz and Tony Crawford: 以下是Peter Prinz和Tony Crawford的C in a Nutshell

The setjmp() macro saves the current environment at the time of the call in a buffer specified by its argument. setjmp()宏将调用时的当前环境保存在其参数指定的缓冲区中。 The environment includes the stack, and with it all variables that have automatic storage duration. 环境包括堆栈,以及具有自动存储持续时间的所有变量。

Here is what ISO/IEC 9899:TC2 has to say in section 7.13: 以下是ISO / IEC 9899:TC2在7.13节中要说的内容:

The environment of a call to the setjmp macro consists of information sufficient for a call to the longjmp function to return execution to the correct block and invocation of that block, were it called recursively. 调用setjmp宏的环境包含足以调用longjmp函数的信息,以便将执行返回到正确的块并调用该块,如果它是递归调用的。 It does not include the state of the floating-point status flags, of open files, or of any other component of the abstract machine. 它不包括浮点状态标志,打开文件或抽象机器的任何其他组件的状态。

Here is an interesting reference by PJ Plauger in his book, The Standard C Library : 以下是PJ Plauger在他的书“标准C库”中的一个有趣的参考:

One of the dangers [of implementing setjmp] lies in expression evaluation. [实施setjmp]的危险之一在于表达评估。 A typical computer has some number of registers that it uses to hold intermediate results while evaluating an expression. 典型的计算机具有一定数量的寄存器,用于在评估表达式时保存中间结果。 Write a sufficiently complex expression, however, and you may exhaust the available registers... setjmp must guess how much "calling context" to store in the jmp_buf data object. 但是,写一个足够复杂的表达式,你可能会耗尽可用的寄存器... setjmp必须猜测要在jmp_buf数据对象中存储多少“调用上下文”。 It is a safe bet that certain registers must be saved. 可以肯定的是,必须保存某些寄存器。

And finally, from Expert C Programming by Peter Van Der Linden. 最后,来自Peter Van Der Linden的Expert C Programming

Setjmp saves a copy of the program counter and the current pointer to the top of the stack. Setjmp将程序计数器的副本和当前指针保存到堆栈顶部。

Based on the above information, it looks to me like the "current environment" is left up to the implementation. 基于以上信息,我认为“当前环境”是由实施所决定的。

It's just the registers that need to be preserved across a function call according to the platforms ABI. 根据平台ABI,它只是需要在函数调用中保留的寄存器。

Source: disassembling setjmp on x86, x64, arm32, arm64 on various operating systems. 来源:在各种操作系统上拆解x86,x64,arm32,arm64上的setjmp。

The setjmp() function saves the contents of most of the general purpose registers, in the same way as they would be saved on any function entry. setjmp()函数保存大多数通用寄存器的内容,其保存方式与保存在任何函数条目中的方式相同。 It also saves the stack pointer and the return address. 它还保存堆栈指针和返回地址。 All these are placed in the buffer. 所有这些都放在缓冲区中。 It then arranges for the function to return zero. 然后它安排函数返回零。

The longjmp() function restores the general purpose registers and the stack pointer and then does a jump to the previously saved return address. longjmp()函数恢复通用寄存器和堆栈指针,然后跳转到先前保存的返回地址。 In practice it may do this explicitly, or by setting up the stack and executing a normal function return. 在实践中,它可以显式地执行此操作,或者通过设置堆栈并执行正常的函数返回。 On this occasion the function returns a non-zero value. 在这种情况下,该函数返回一个非零值。

The principle is the same, but the detail has varied quite a bit across the many different CPUs I have encountered. 原理是一样的,但是我遇到的许多不同的CPU的细节差别很大。

From the setjmp manpage 来自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.

Essentially, it remembers the current stack location and register state. 从本质上讲,它会记住当前的堆栈位置和寄存器状态。 When you call longjmp, you jump back to the same program counter and stack location with some additional registers are restored. 当你调用longjmp时,你会跳回到同一个程序计数器和堆栈位置,并恢复一些额外的寄存器。

These are often referred to as "non-local gotos". 这些通常被称为“非本地的”。 They are not like a fork that would copy memory state or anything like that. 它们不像是能够复制内存状态或类似内容的分支。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM