T.R | Title | User | Personal Name | Date | Lines |
---|
2166.1 | | DECCXL::OUELLETTE | mudseason into blackfly season | Mon Apr 28 1997 12:33 | 25 |
| From the ANSI and ISO C language standard.
4.6.2 Restore Calling Environment
4.6.2.1 The longjmp function
Paragraph at line 11:
All accessible objects have values as of the time lonjmp 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 the longjmp call are indeterminate.
To have portable code, you must qualify those automatic variables which
must stay updated with volatile.
On Windows NT on Alpha there are two setjmp/longjmp pairs.
One interoperates with C++ Exception Handling and C Structured Exception
Handling by unwinding the stack frames to call dtors and finally handlers
as well as perhaps being intercepted by catch or except clauses.
This has the sideeffect of restoring automatics to their most recent value.
Perhaps one of the several setjmp/longjmp implementations on Unix (you are
on Unix right?) does that. I'll let someone more familliar give a
definitive answer.
|
2166.2 | notes collision | SPECXN::DERAMO | Dan D'Eramo | Mon Apr 28 1997 12:36 | 53 |
| >It seems that the only way to NOT have a restored to it's pre-setjmp
>value is to declare it volatile.
Yes. Actually, static will work too, but beware if the
routine can be "active" more than once (recursive calls,
AST's, multiple threads, signals, etc.). Volatile is
definitely the way to go.
From topic 935 here:
>935.0
>In the ANSI C standard section 4.6.2.1 page 120 it says
>
> All accessible objects have values as of the time longjmp
> 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 the longjmp call are indeterminate.
There is similar language in the DEC C Run-Time Library
Reference Manual for OpenVMS Systems in the "man page" for
setjmp:
> The setjmp function preserves the hardware general purpose
> registers, and the longjmp function restores them. After a
> longjmp, all variables have their values as of the time of the
> longjmp except for local automatic variables not marked
> volatile. These variables have indeterminate values.
[Hmmm...notice how that promises less than the standard does?]
Note that while the "obvious implementation" of setjmp/longjmp
will either leave the last assigned value in a local automatic
nonvolatile variable or will restore its pre-setjmp value, the
standard does not limit an implementation to just those
choices. If it is a local nonstatic nonvolatile variable that
was modified between the setjmp and longjmp, then after the
longjmp its value is "indeterminate".
If they left out needed volatile qualifiers then their code is
broken and they cannot rely upon /NOOPTIMIZE to fix it. [I
wouldn't be surprised if the language-specific front-end plus
common back-end compiler architecture left it out of the C/C++
compiler teams' hands. Even if that is not the case, I doubt
that setjmp/longjmp and /NOOPTIMIZE would have been implemented
with avoidance of this effect in mind.] The customers have to
go through the code and put the volatile qualifiers in. (Their
code may not even use setjmp/longjmp directly, they may be using
setjmp/longjmp via the TRY/CATCH/CATCH_ALL/ENDTRY and
TRY/FINALLY/ENDTRY macros in the threads exception interface.)
Dan
|
2166.3 | Thanks | CSC32::J_HENSON | Don't get even, get ahead! | Tue Apr 29 1997 11:53 | 7 |
| Thanks,
I'll pass it on.
Jerry
P.S. I'm using OpenVMS, not Unix.
|
2166.4 | volatile pointer is ignored | CSC32::J_HENSON | Don't get even, get ahead! | Fri May 02 1997 12:23 | 45 |
| Still using Dec C V5.5-003 on OpenVMS Alpha V7.0
I passed on the replies to my customer, and he has come back with another
test case. This time, it appears that the compiler is ingoring
pointers that are declared as volatile. The code is listed below.
When you run this (and it doesn't matter whether it's compiled
/opt or /noop), the value in the volatile int variable a is left alone,
which is what I expect. However, the value of the volatile int
pointer variable apointer is restored to the value it had prior
to the call to setjmp. This is not what I expect.
Could someone try this with v5.6 and see if the behavior 's the same?
Also, this appears to be a bug to me, but I've been wrong before (lots
of times).
Thanks,
Jerry
======================================================
#include <setjmp.h>
#include <stdio.h>
main()
{
volatile int a = 0;
volatile int *apointer = NULL;
jmp_buf env;
if( setjmp( env ) == 0 ) {
apointer = &a;
a = 1;
printf("Before longjmp\n");
printf("apointer = %x\n",apointer);
printf( "a = %d\n", a );
longjmp( env, 1 );
} else {
printf("After longjmp\n");
printf("apointer = %x\n",apointer);
printf( "a = %d\n", a );
}
}
|
2166.5 | the pointer was not volatile... | DECCXL::OUELLETTE | mudseason into blackfly season | Fri May 02 1997 13:16 | 29 |
| Your customer in this declaration:
volatile int *apointer = NULL;
has declared a pointer to a volatile int.
His intention was probably to declare a volatile pointer to an integer.
int * volatile apointer = NULL;
Or perhaps a volatile pointer to a volatile int.
In that case:
volatile int * volatile apointer = NULL;
Most users find writing this with a typedef makes things clearer:
typedef int *pint;
volatile pint apointer = NULL;
or:
typedef volatile int *pvint;
volatile pvint apointer = NULL;
"cc test.c -source_listing -Wf,-dump,initial" will make a listing file
(test.lis) with a dump of what the compiler's frontend is telling the
compiler's backend to do. You can look at the placement of IO_VOLATILE
and MUST_READ, MUST_WRITE attributes on FETCHs and STOREs to educate
yourself on how the qualifiers are interpreted.
|
2166.6 | Thanks | CSC32::J_HENSON | Don't get even, get ahead! | Mon May 05 1997 10:27 | 21 |
| >> <<< Note 2166.5 by DECCXL::OUELLETTE "mudseason into blackfly season" >>>
>> -< the pointer was not volatile... >-
>>Your customer in this declaration:
>> volatile int *apointer = NULL;
>>has declared a pointer to a volatile int.
>>His intention was probably to declare a volatile pointer to an integer.
>> int * volatile apointer = NULL;
>>Or perhaps a volatile pointer to a volatile int.
>>In that case:
>> volatile int * volatile apointer = NULL;
Thanks. That was it. I have always found pointers a bit confusing,
especially in situations such as this. Thanks for clearing this up.
Jerry
|