void testproc (void)
{
longjmp(environment, 1);
}
long do_setjmp (void)
{
return setjmp(environment);
}
long testing (void)
{
long status;
status = setjmp(environment);
// status = do_setjmp();
if (status == 0) {
testproc();
return -1;
}
return status;
}
Prog starts in 'testing', calls setjmp then calls testproc which calls
longjmp.
Now, if I call setjmp from 'testing', it works. First time, returned
status is zero,
so testproc gets called, second time is 1, so I return the status(1).
But, if I call setjmp with do_setjmp, when I call testproc and it
calls longjmp,
longjmp does return where it is supposed to (in do_setjmp) but
do_setjmp
then returns to 'return -1;', i.e. after a call to testproc, and not
to 'if (status == 0)'.
Why?
Cheers,
Aleksandar
Because the function do_setjmp() that did the setjmp has terminated
execution when testproc does longjmp(), and that's prohibited by
7.13.2.1#2:
The longjmp function restores the environment saved by the most
recent invocation of the setjmp macro in the same invocation of
the program with the corresponding jmp_buf argument. If (..)
the function containing the invocation of the setjmp macro has
terminated execution (for example, by executing a return statement
(..)) in the interim (..) the behavior is undefined.
Francois Grieu
setjmp() returns int. Why are you storing the result in a long?
(Not that that has anything to do with the problems you're seeing.)
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
>> Why?
>
> Because the function do_setjmp() that did the setjmp has terminated
> execution when testproc does longjmp(), and that's prohibited by
> 7.13.2.1#2:
Ah, but it triggers UB long before that. 7.13.1.1#4 and #5:
[#4] An invocation of the setjmp macro shall appear only in
one of the following contexts:
-- the entire controlling expression of a selection or
iteration statement;
-- one operand of a relational or equality operator with
the other operand an integer constant expression, with
the resulting expression being the entire controlling
expression of a selection or iteration statement;
-- the operand of a unary ! operator with the resulting
expression being the entire controlling expression of a
selection or iteration statement; or
-- the entire expression of an expression statement
(possibly cast to void).
[#5] If the invocation appears in any other context, the
behavior is undefined.
Right. The working variant of OP's code also infringes on that with
status = do_setjmp();
This is UB, although many if not most implementations are happy with it.
Francois Grieu