What is an automatic variable in this setjmp/longjmp context?
Advanced Programming开发者_如何学Go in the UNIX Environment by W. Richard Stevens states:
"What are the the states of the automatic variables and register variables in the main function?"
with regard to what happens when you longjmp
back to main (or another function) from somewhere lower down the stack.
It goes on to say:
"It depends. Most implementations do not try to roll back these automatic variables and register variables, but all that the standards say is that their values are indeterminate. If you have an automatic variable that you don't want rolled back, define it with the
volatile
attribute. Variables that are declared global or static are left alone whenlongjmp
is executed.
It seems like he's saying that normal stack-variables will not have their values set back to what they were at the time of the setjmp - but then the rest of the function couldn't rely on its stack variables after the longjmp back to it which seems crazy, so I'm guessing I'm wrong.
Can someone define "automatic variables" for me and explain what specifically isn't set back to its original value and why that is?
All it's saying is that if
- you have an automatic (function-local non-static) variable that's not declared
volatile
; and - you change the value of the variable between
setjmp
andlongjmp
then after the longjmp
the value of that variable becomes indeterminate.
I believe this has to do with the possibility of such variables residing in CPU registers rather than in RAM, and the associated difficulty of preserving the values of such variable across the longjmp
.
Here is a quote from the gcc
manual:
If you use
longjmp
, beware of automatic variables. ISO C says that automatic variables that are not declaredvolatile
have undefined values after alongjmp
. And this is all GCC promises to do, because it is very difficult to restore register variables correctly, and one of GCC's features is that it can put variables in registers without your asking it to.
If the potential loss of variable values is a problem in your use case, declare the relevant variables as volatile
.
"Automatic variables" is an old term for ordinary (not declared with register or static) local variables, which goes back to terminology used in the C standard and the original meaning of the auto
keyword. See sections 6.2.4 and 6.7.1 of the standard
As for this:
but then the rest of the function couldn't rely on its stack variables after the longjmp back to it which seems crazy
The idea is that you're not supposed to modify them in the first place if you're going to longjmp because then you can't know what's going to happen.
The reason is that longjmp may restore state such as processor registers, which automatic variables may have been mapped to (there is no guarantee that they will be on "the stack" or in memory at all. And even if they do exist in memory, some operations may not [unless it is declared volatile] directly access the memory but may access a processor register which the value has already been loaded into)
Your question is kind of odd because it implies you would want them to be restored [i.e. your modifications in intervening functions to be erased] - in general this caveat is warning that they may be restored by accident when it's not expected. "Not restored" doesn't mean "unusable" [though the standard DOES declare them unusable because it might restore a cached register but not the memory so you'll get inconsistent results], it means "has the value a later function wrote to it (because you passed the address intending for it to be written to)".
Automatic variables are regular function-local variables - since they are allocated on the stack and you do not have to take care about their memory they are called automatic.
See http://en.wikipedia.org/wiki/Automatic_variable for a more in-depth descriptions.
I can't define an "automatic variable", but maybe that can help you to understand what happens during a setjump
:
(some of) the CPU registers and saved into a file.
and during longjump
:
the value of the CPU registers is reset to the saved value.
nothing else! (here is an example)
So during the longjump
, you just come back higher in the stack, with all your variables saved in the memory untouched, and some (not all of them) of the registers, in particular the stack pointer
and the instruction pointer
reset to the value they had during the setjmp
.
auto
means anything that's local to the function and hasn't specifically been defined as static
. It's probably worth noting that the standard specifies pretty much the behavior he states (§7.13.2/3):
All accessible objects have values, and all other components of the abstract machine 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.
精彩评论