473,608 Members | 2,077 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

longjmp and volatile variables

Hello,
I have a problem with restoring variables in the setjmp/longjmp
functions:

K&R2 for longjmp says:
"Accessible objects have the same value they had when longjmp was
called, except for automatic non volatile variables of the function
invoking setjmp, these will be undefined if modified after the setjmp
call"

MSDN for longjmp says:
"The values of all variables (except register variables) that are
accessible to the routine receiving control contain the values they had
when longjmp was called. The values of register variables are
unpredictable."
[...]
"Do not assume that the values of the register variables will remain
the same. The values of register variables in the routine calling
setjmp may not be restored to the proper values after longjmp is
executed."

I think, but I'm not sure, that both these mean
"the variables accessible from both the caller of setjmp and the caller
of longjmp
are not assured to keep the value if the compiler stores them in
registers"

Correct?

But... when a variable is stored in registers?

The solution?
maybe this one: "volatile int x;" ?
Is this to be put in front of any local variable of the calling
function?

Thank you in advance!
Claus

Apr 29 '06 #1
6 3217
Clausfor a écrit :
The solution?
maybe this one: "volatile int x;" ?
Is this to be put in front of any local variable of the calling
function?


That will work, yes.

Another, less portable solution is to read your compiler's documentation
and see what happens when optimizations are NOT enabled. Maybe in that
case the compiler does not use register variables and the problem does
not exist.
Apr 29 '06 #2
In article <11************ **********@e56g 2000cwe.googleg roups.com>,
Clausfor <cl******@gmail .com> wrote:
I think, but I'm not sure, that both these mean
"the variables accessible from both the caller of setjmp and the caller
of longjmp
are not assured to keep the value if the compiler stores them in
registers"
The local variables in the function where longjmp() is called are
irrelevant: you're returning from that function so they can't be
accessed anyway (except in the trivial case where longjmp() is called
from the same function invocation as setjmp()). The variables at risk
are those in the function invocation where setjmp() was called.

It may be useful to know the reason for this. A common way to implement
setjmp() is to store the current values of all registers, and restore
them when longjmp() is called. This will restore the stack pointer to
point to the frame that was current when setjmp() was called, so that
variables stored on the stack will be correct. But variables stored
in registers will be restored to their values when setjmp() was called,
losing any changes to them between the setjmp() and longjmp().

The standard, as usual, does not say that this particular "incorrect"
behaviour will occur; it just says that such any variables that
*might* be in registers are undefined.
But... when a variable is stored in registers?


Potentially, any time when it isn't declared volatile. So any local
variables whose value must be right after the longjmp() should be declared
volatile.

-- Richard
Apr 29 '06 #3
>In article <11************ **********@e56g 2000cwe.googleg roups.com>,
Clausfor <cl******@gmail .com> wrote:
I think, but I'm not sure, that both these mean
"the variables accessible from both the caller of setjmp and the caller
of longjmp
are not assured to keep the value if the compiler stores them in
registers"
In article <e3***********@ pc-news.cogsci.ed. ac.uk>
Richard Tobin <ri*****@cogsci .ed.ac.uk> wrote:
The local variables in the function where longjmp() is called are
irrelevant: you're returning from that function so they can't be
accessed anyway (except in the trivial case where longjmp() is called
from the same function invocation as setjmp()). The variables at risk
are those in the function invocation where setjmp() was called.
Indeed.
It may be useful to know the reason for this. A common way to implement
setjmp() is to store the current values of all registers, and restore
them when longjmp() is called. This will restore the stack pointer to
point to the frame that was current when setjmp() was called, so that
variables stored on the stack will be correct. But variables stored
in registers will be restored to their values when setjmp() was called,
losing any changes to them between the setjmp() and longjmp().
Or, equivalently, the implementation might save and restore *only*
those registers critical to locating the correct stack frame (really,
"overall execution context"). On most machines, excluding the x86
that nobody uses :-) , this avoids a whole lot of often-useless
work, making setjmp() execute noticeably faster.

In either case, to elaborate a bit, consider the following C source
fragment (which I do not claim is any good or even any use; it is
just for illustration, especially the "block1" and "block2" labels):

#include <setjmp.h>

jmp_buf label;

void f(T1 arg1, T2 arg2) {
while (someloop) {

if (somecond) {
register int x;

block1:
x = 42;
... some code here ...
if (setjmp(label)) {
printf("jumped back, in block 1, x = %d\n", x);
goto block2;
}
x += 3;
... more code here, calling g() ...
}

if (othercond) {
register int y;

block2:
... still more code here, calling h() ...
}

}
}

Suppose that the compiler uses the *same* machine register for both
x and y. This is a perfectly reasonable thing to do, since the
two variables have separate scopes. When "x" disappears, "y"
appears, and vice versa: perfect conditions for sharing.

Now, when -- in your function that uses longjmp(), say inside g()
-- you execute a "goto label" (via longjmp(label), which is just
a particularly powerful kind of "go to"), this will either restore
x to the saved value, if the implementation saves all the registers;
or it will fail to restore x.

Suppose it chooses to restore x to the saved value. In this case,
if you were inside block1, all is somewhat well, except that x has
"magically" (via the restore) had the 3 subtracted back out. That
is, the flow of control was as follows:

- enter block 1
- set x to 42
- call setjmp
. save the point of the call
. save the register holding x (42)
. return 0
- add 3 to x (now it is 45)
- execute "more code":
. call some function g()
. longjmp(label):
* restore x (to 42)
* terminate function g() and resume f() at the "if (setjmp(label)) "
(making setjmp() return some nonzero value this time)
- print x (42), which apparently has not had 3 added.

On the other hand, if the implementation chooses *not* to restore
x, it *may* still have 45 in it. This would be even better, since
this would make x act like a regular variable. Also, it is "faster",
because the setjmp and longjmp do not have to modify the register.
But what if "g" had a "register int z" that used the same register?
Then x would quite likely "magically" acquire z's value.

Now, if you were to get out of the first block in f() safely, and
get into block2, and call h() and have h() longjmp back to f(),
and print x there, this would either restore the saved value (42),
or leave the register alone. Of course, such code is technically
undefined -- you left the block that defined x and then re-entered
it (via the goto that longjmp() does) -- so you should not expect
any particular value anyway. But now let me modify the original
code a bit, to remove the sub-block for x. I will also remove the
"register" keyword, since it is just a hint anyway.

void f(T1 arg1, T2 arg2) {
int x;

while (someloop) {
if (somecond) {
block1:
x = 42;
... some code here ...
if (setjmp(label)) {
printf("jumped back, in block 1, x = %d\n", x);
goto block2;
}
x += 3;
... more code here, calling g() ...
}
if (othercond) {
int y;
block2:
... still more code here, calling h() ...
}
}
}

Now if h() calls longjmp(label), the effect is "almost defined"
(with the word "almost" inserted because of the "volatile" issue
being described here), because the variable x is defined way up
at the top of f().

Suppose, however, our compiler is a decent one, that optimizes
well. It notices that x is only used in block1; and of course
y is only used in block2. It therefore realizes that it can use
a single machine register to hold *both* variables, just as we did
"manually" in the first version of the code.

This time, if we longjmp() from h(), and setjmp() and longjmp() do
*not* save and restore the machine register, we can get the value
that was in y printed when we reach the printf(). Of course, if
the implementation' s setjmp()/longjmp() save and restore the
register, we get 42 -- the "x += 3" has again "magically vanished".
The standard, as usual, does not say that this particular "incorrect"
behaviour will occur; it just says that such any variables that
*might* be in registers are undefined.
And of course:
But... when a variable is stored in registers?

Potentially, any time when it isn't declared volatile. ...


So this means that you have to write f() above as:

void f(T1 arg1, T2 arg2) {
volatile int x;

while (someloop) {
if (somecond) {
block1:
x = 42;
... some code here ...
if (setjmp(label)) {
printf("jumped back, in block 1, x = %d\n", x);
goto block2;
}
x += 3;
... more code here, calling g() ...
}
if (othercond) {
int y;
block2:
... still more code here, calling h() ...
}
}
}

That way, whether g() or h() (or anything they call) use longjmp
to go back to the "label", x will have a predictable value -- 45
-- and everything will be guaranteed to work.

Note that, in this *particular* case, "y" need not be declared
volatile, because block2 cannot use it without first setting it
to some value. It is of course safe to use "volatile" on y too,
but it is not required (and may inhibit some optimization).

Your best bet is usually to avoid longjmp() entirely, because it
is a very powerful "goto", and "goto" is best used sparingly, if
at all. There are restrictions on where you can use setjmp() and
longjmp(), but compilers rarely enforce them, and if you accidentally
misuse them, not only does your program usually crash, many debuggers
get confused in the process and cannot help you pinpoint the problem.

(The reason is that longjmp() often just "sets" the machine's stack
and/or frame pointer registers, and if the values it sets are
garbage, the debugger has no clue where to look for the problem.
Worse, after setting these registers, longjmp just "sets" the
program-counter / instruction-pointer register, eradicating all
traces of its own handiwork. So you get a mysterious failure at
the jumped-to point, with no record of *why* you got to that point.
All the debugger can tell you is "the stack frames are all trashed,
and the program was executing in this apparently-randomly-chosen
function or data area, at the time the crash occurred.")
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Apr 29 '06 #4
"Clausfor" <cl******@gmail .com> wrote:
# Hello,
# I have a problem with restoring variables in the setjmp/longjmp
# functions:

setjmp() is usually implemented by taking a snapshot of all
the registers and storing that in the jump buffer. longjmp
then restores that snapshot except the for the register that
holds the return value. This means any variable in a register
at the setjmp will have its value restored by a longjmp.

ANSI doesn't know which or if any variables can be in a
register: that's up to the implementor. But it does know that
it's possible, hence the vaguely ominous warning. Microsoft
is referring to their particular implementation, of which
they might be more certain (though it is, after all,
Microsoft).

volatile variables are stored in way that they can be
asynchronously modified, and the compiler must guarentee
their current values are always accessed. On current and
foreseeable architecures, that means the variables are
stored in memory not registers, and they are not cached
in registers either. This means volatile variables are
not affected by setjmp/longjmp. Many other variables would
also be unaffected, but less predictably so.

--
SM Ryan http://www.rawbw.com/~wyrmwif/
This is one wacky game show.
Apr 29 '06 #5
jacob navia <ja***@jacob.re mcomp.fr> wrote:
Clausfor a écrit :
The solution?
maybe this one: "volatile int x;" ?
Is this to be put in front of any local variable of the calling
function?
That will work, yes.


It is the only correct option.
Another, less portable solution is to read your compiler's documentation
and see what happens when optimizations are NOT enabled. Maybe in that
case the compiler does not use register variables and the problem does
not exist.


Do _not_ do this. It does not solve anything, will make your program
unportable, and is likely to make that particular function less
efficient, to boot. Why apply a "solution" that only has downsides?

Richard
May 1 '06 #6
rl*@hoekstra-uitgeverij.nl (Richard Bos) writes:
jacob navia <ja***@jacob.re mcomp.fr> wrote:
Clausfor a icrit :
> The solution?
> maybe this one: "volatile int x;" ?
> Is this to be put in front of any local variable of the calling
> function?


That will work, yes.


It is the only correct option.


Another would be to not modify any local variables of the
function that calls setjmp() before longjmp() (may be) called.
This is not necessarily difficult.
--
"The way I see it, an intelligent person who disagrees with me is
probably the most important person I'll interact with on any given
day."
--Billy Chambless
May 1 '06 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

17
7049
by: Radde | last post by:
HI, Can volatile variables be accessed by many processess..or only one process can access it.. Cheers..
2
2280
by: Thomas Baruchel | last post by:
Hi, wondering about: func1: setjmp() ; func2(); func2: {FILE *f; f = fopen(); func3(); fclose(f)} func3 : if() longjmp; else return; Note that FILE *fis a local variable in func2.
2
1867
by: Mantorok Redgormor | last post by:
is there a portable way of implementing exception handling with setjmp, longjmp? restoring the state of a program and such really seems like I am asking for undefined behavior. -- nethlek
22
6050
by: Nimmi Srivastav | last post by:
Can someone kindly clarify the distinction between long jumps and gotos? Why is one frowned upon and not the other? Is there really any situation where use of longjmp becomes inevitable? A real-life code snippet would surely help. Regards, Nimmi
14
19305
by: google-newsgroups | last post by:
Hello, even (or because?) reading the standard (ISO/IEC 9899/1999) I do not understand some issues with volatile. The background is embedded programming where data is exchanged between main program flow and interrupts. At the organisation I work, instead of declaring a variable volatile, it is casted to volatile when necessary:
8
2407
by: Zheng Da | last post by:
I wrote a simple one as follow: typedef struct __myjmp_buf { int efp; int epc; }myjmp_buf; int mysetjmp(myjmp_buf env) {
3
1892
by: no_click_there | last post by:
Hi, I'm learning to use the setjmp/longjmp functions and still can't really grasp what's going on here. I'd basically like to be able to jump back and forth from (or to) two given functions. Let's consider the following toy-example (yes, the example is stupid but never mind...) BEGIN CODE =====================
94
30258
by: Samuel R. Neff | last post by:
When is it appropriate to use "volatile" keyword? The docs simply state: " The volatile modifier is usually used for a field that is accessed by multiple threads without using the lock Statement (C# Reference) statement to serialize access. " But when is it better to use "volatile" instead of "lock" ?
10
3422
by: S James S Stapleton | last post by:
Is volatile necessary anymore? I have a two-thread piece of code I've been testing to figure out what volatile does (fairly simple code, uses pthreads). I have an update thread (variables passed as volatile) and a print thread (one variable volatile, the other, not). There is no difference in the behavior of the volatile and nonvolatile thread. I'm compiling this with gcc, using the -O2 and -pthreads flags. The sudocode is at the end....
0
8063
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8003
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8478
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8152
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
6817
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6014
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5476
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
1
2474
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1598
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.