[setjmp/longjmp] stack limitation


M

m.labanowicz

Hello,

Is there any restriction releated to the
usage of stack in branches after longjmp ?

Following example makes mudflap violation.

--------------------------------------------------
$ gawk '{printf("/*%02u:*/ %s\n", NR, $0);}' main.c
/*01:*/ #include <setjmp.h>
/*02:*/ #include <string.h>
/*03:*/ #include <stdlib.h>
/*04:*/ int main(void) {
/*05:*/ volatile int var = 56;
/*06:*/ jmp_buf jmp;
/*07:*/ if (0 == setjmp(jmp)) {
/*08:*/ char bar [15];
/*09:*/ memset(bar, 0, sizeof(bar));
/*10:*/ var = 45;
/*11:*/ longjmp(jmp, 1);
/*12:*/ }
/*13:*/ else {
/*14:*/ char foo [11];
/*15:*/ memset(foo, var, sizeof(foo));
/*16:*/ }
/*17:*/ return EXIT_SUCCESS;
/*18:*/ }
$ gcc --version | head -n1
gcc (Ubuntu/Linaro 4.7.2-11precise2) 4.7.2
$ gcc -ansi -pedantic -W -Wall -Werror -fmudflap main.c -lmudflap -o a.out
$ export MUDFLAP_OPTIONS=
$ ./a.out
*******
mudflap violation 1 (register): time=1360844131.327763 ptr=0x7fff06e922d0 size=11
pc=0x7f6a2945f5f1
/usr/lib/x86_64-linux-gnu/libmudflap.so.0(__mf_register+0x41) [0x7f6a2945f5f1]
./a.out(main+0xc0) [0x400a9c]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed) [0x7f6a290b876d]
Nearby object 1: checked region begins 0B into and ends 10B into
mudflap object 0x7c1d20: name=`main.c:8:10 (main) bar'
bounds=[0x7fff06e922d0,0x7fff06e922de] size=15 area=stack check=0r/1w liveness=1
alloc time=1360844131.327758 pc=0x7f6a2945f5f1
number of nearby objects: 1
*******
mudflap violation 2 (unregister): time=1360844131.328163 ptr=0x7fff06e922d0 size=11
pc=0x7f6a2945f196
/usr/lib/x86_64-linux-gnu/libmudflap.so.0(__mf_unregister+0x36) [0x7f6a2945f196]
./a.out(main+0xef) [0x400acb]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed) [0x7f6a290b876d]
Nearby object 1: checked region begins 0B into and ends 10B into
mudflap object 0x7c1d20: name=`main.c:8:10 (main) bar'
number of nearby objects: 1
--------------------------------------------------

If size of 'foo' array is set to 3 then everything is correct.

Or maybe there is a BUG in MUDFLAP...

Regards
 
Ad

Advertisements

J

James Kuyper

Hello,

Is there any restriction releated to the
usage of stack in branches after longjmp ?

Not as such, since the C standard never mentions the stack, and can be
implemented even on machines that don't have a stack. However, there are
potential problems associated with the use of longjmp() that involve
objects with automatic storage duration; on machines which have a stack,
most implementations of C (but not all) will place objects with
automatic storage duration on the stack (for example, some
implementations allocate such memory in the form of "activation records"
from the heap).
Following example makes mudflap violation.

--------------------------------------------------
$ gawk '{printf("/*%02u:*/ %s\n", NR, $0);}' main.c
/*01:*/ #include <setjmp.h>
/*02:*/ #include <string.h>
/*03:*/ #include <stdlib.h>
/*04:*/ int main(void) {
/*05:*/ volatile int var = 56;
/*06:*/ jmp_buf jmp;
/*07:*/ if (0 == setjmp(jmp)) {
/*08:*/ char bar [15];
/*09:*/ memset(bar, 0, sizeof(bar));
/*10:*/ var = 45;
/*11:*/ longjmp(jmp, 1);
/*12:*/ }
/*13:*/ else {
/*14:*/ char foo [11];
/*15:*/ memset(foo, var, sizeof(foo));
/*16:*/ }
/*17:*/ return EXIT_SUCCESS;
/*18:*/ }

(7.13.2.1p3) says that
All accessible objects have values, and all other components of the abstract machine249)
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.

The array 'bar' is an object with automatic storage duration, local to
the function containing the invocation of the corresponding setjmp
macro, which does not have volatile-qualified type, which was changed
between the setjmp invocation and the longjmp() call. However, it's
lifetime ends with the longjmp call, so it's value never gets a chance
to become indeterminate. I'm not at all sure why MUDFLAP is complaining.
It might have something to do with the fact that your code is simplified
to the point of contain completely pointless code - you can remove bar,
foo, and both calls to memset() without causing any change to the
defined behavior of your code. Perhaps that confused MUDFLAP. If you had
similar code where successful execution of memset() affects the
observable behavior, perhaps the MUDFLAP message would make more sense?


....
Or maybe there is a BUG in MUDFLAP...

Always a possibility - one you should take up with whoever is
responsible for MUDFLAP.
 
X

Xavier Roche

Le 14/02/2013 13:29, (e-mail address removed) a écrit :
Is there any restriction releated to the
usage of stack in branches after longjmp ?
Or maybe there is a BUG in MUDFLAP...

According to this 2003 paper, use of (set/long)jmp is not supported with
mudflap:
<http://ols.fedoraproject.org/GCC/Reprints-2003/mudflap.pdf>

"Tracking the lifetime of variables in a scope is tricky because control
can leave a scope in several places. (Grossly, it might even enter in
several places using goto.) The C++ constructor/destructor mechanism
provides the right model for attaching code to object scope boundaries.
Luckily, GCC provides the necessary facilities even to trees that come
from the C frontend. There are several variants: the CLEANUP_EXPR node
type, and the more modern TRY_FINALLY_EXPR. Both tree types take a block
(a statement list) and another statement (a cleanup) as arguments. The
former is interpreted as a sequence of statements such as any that
follow a declaration within a given scope/block. The latter is a
statement that should be evaluated whenever the scope is exited, whether
that happens by break, return, or just plain falling off the end. (*)

(*) However, abrupt exit from a scope via a longjmp is not speciï¬cally
handled at this time."
 
S

Shao Miller

Hello,

Is there any restriction releated to the
usage of stack in branches after longjmp ?

C doesn't have a stack.
Following example makes mudflap violation.

mudflap violations != C problems, but there is obviously overlap.
--------------------------------------------------
$ gawk '{printf("/*%02u:*/ %s\n", NR, $0);}' main.c
/*01:*/ #include <setjmp.h>
/*02:*/ #include <string.h>
/*03:*/ #include <stdlib.h>
/*04:*/ int main(void) {
/*05:*/ volatile int var = 56;
/*06:*/ jmp_buf jmp;
/*07:*/ if (0 == setjmp(jmp)) {
/*08:*/ char bar [15];
/*09:*/ memset(bar, 0, sizeof(bar));

Redundant parentheses:

memset(bar, 0, sizeof bar);

Consider how silly the following seems:

((memset)((bar), (0), (sizeof (bar))));
/*10:*/ var = 45;
/*11:*/ longjmp(jmp, 1);
/*12:*/ }
/*13:*/ else {
/*14:*/ char foo [11];
/*15:*/ memset(foo, var, sizeof(foo));
/*16:*/ }
/*17:*/ return EXIT_SUCCESS;
/*18:*/ }
$ gcc --version | head -n1
gcc (Ubuntu/Linaro 4.7.2-11precise2) 4.7.2
$ gcc -ansi -pedantic -W -Wall -Werror -fmudflap main.c -lmudflap -o a.out
$ export MUDFLAP_OPTIONS=
$ ./a.out
*******
mudflap violation 1 (register): time=1360844131.327763 ptr=0x7fff06e922d0 size=11
pc=0x7f6a2945f5f1
/usr/lib/x86_64-linux-gnu/libmudflap.so.0(__mf_register+0x41) [0x7f6a2945f5f1]
./a.out(main+0xc0) [0x400a9c]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed) [0x7f6a290b876d]
Nearby object 1: checked region begins 0B into and ends 10B into
mudflap object 0x7c1d20: name=`main.c:8:10 (main) bar'
bounds=[0x7fff06e922d0,0x7fff06e922de] size=15 area=stack check=0r/1w liveness=1
alloc time=1360844131.327758 pc=0x7f6a2945f5f1
number of nearby objects: 1
*******
mudflap violation 2 (unregister): time=1360844131.328163 ptr=0x7fff06e922d0 size=11
pc=0x7f6a2945f196
/usr/lib/x86_64-linux-gnu/libmudflap.so.0(__mf_unregister+0x36) [0x7f6a2945f196]
./a.out(main+0xef) [0x400acb]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed) [0x7f6a290b876d]
Nearby object 1: checked region begins 0B into and ends 10B into
mudflap object 0x7c1d20: name=`main.c:8:10 (main) bar'
number of nearby objects: 1
--------------------------------------------------

If size of 'foo' array is set to 3 then everything is correct.

Or maybe there is a BUG in MUDFLAP...

If it's a C question, there's a C answer. If it's a mudflap question,
there's a mudflap answer. I didn't spot any C problems in your code,
for what it's worth.
 
K

Keith Thompson

Shao Miller said:
C doesn't have a stack.

That's an oversimplification.

It's true, as I've said many times myself, that the word "stack"
doesn't appear in the C standard. It's also true that a C
implementation needn't use a contiguous stack, and there are a few
that don't.

On the other hand, C function call semantics require some sort of
underlying last-in first-out data structure (whether it's implemented
as a contiguous growing memory stack or not) -- and the vast majority
of C implementations *do* use a contiguous memory stack.

[...]
 
S

Shao Miller

Shao Miller said:
C doesn't have a stack.

That's an oversimplification.

It's true, as I've said many times myself, that the word "stack"
doesn't appear in the C standard. It's also true that a C
implementation needn't use a contiguous stack, and there are a few
that don't.

On the other hand, C function call semantics require some sort of
underlying last-in first-out data structure (whether it's implemented
as a contiguous growing memory stack or not) -- and the vast majority
of C implementations *do* use a contiguous memory stack.

[...]

One point that can be taken from what I said is: If you use a term
that's outside of the language, you might get responses where your
actual query is not addressed. "Restriction related to the usage of
stack": What does this mean? The list of called functions since 'main'?
All storage occupied by objects having automatic storage duration and
which have their addresses taken? "Stack" does not compute*.

* It holds computation values, though. (Joke.)
 
Ad

Advertisements

K

Keith Thompson

Shao Miller said:
Shao Miller said:
On 2/14/2013 07:29, (e-mail address removed) wrote:
Is there any restriction releated to the
usage of stack in branches after longjmp ?

C doesn't have a stack.

That's an oversimplification.

It's true, as I've said many times myself, that the word "stack"
doesn't appear in the C standard. It's also true that a C
implementation needn't use a contiguous stack, and there are a few
that don't.

On the other hand, C function call semantics require some sort of
underlying last-in first-out data structure (whether it's implemented
as a contiguous growing memory stack or not) -- and the vast majority
of C implementations *do* use a contiguous memory stack.

[...]

One point that can be taken from what I said is: If you use a term
that's outside of the language, you might get responses where your
actual query is not addressed. "Restriction related to the usage of
stack": What does this mean? The list of called functions since 'main'?
All storage occupied by objects having automatic storage duration and
which have their addresses taken? "Stack" does not compute*.

Yes, that *can* be taken from what you said, but only by someone who
already understand the issues. The previous poster may have assumed
that C requires a "stack" in the conventional sense. Telling him that
"C doesn't have a stack", while strictly correct, is unlikely to be
helpful.
 
S

Shao Miller

Shao Miller said:
On 2/14/2013 07:29, (e-mail address removed) wrote:
Is there any restriction releated to the
usage of stack in branches after longjmp ?

C doesn't have a stack.

That's an oversimplification.

It's true, as I've said many times myself, that the word "stack"
doesn't appear in the C standard. It's also true that a C
implementation needn't use a contiguous stack, and there are a few
that don't.

On the other hand, C function call semantics require some sort of
underlying last-in first-out data structure (whether it's implemented
as a contiguous growing memory stack or not) -- and the vast majority
of C implementations *do* use a contiguous memory stack.

[...]

One point that can be taken from what I said is: If you use a term
that's outside of the language, you might get responses where your
actual query is not addressed. "Restriction related to the usage of
stack": What does this mean? The list of called functions since 'main'?
All storage occupied by objects having automatic storage duration and
which have their addresses taken? "Stack" does not compute*.

Yes, that *can* be taken from what you said, but only by someone who
already understand the issues.

I disagree, and don't know why you believe that's so. "C doesn't have a
stack" is supposed to remove a mistake. Here's one possible model for
the learning process:

1. Unconscious incompetence
2. Conscious incompetence
3. Conscious competence
4. Unconscious competence

When you don't know what you don't know (#1), someone can spot a mistake
and point it out to you (#2), then you'll [hopefully] be aware of it for
the next time (#3).
The previous poster may have assumed
that C requires a "stack" in the conventional sense.

What is an example of the conventional sense? x86' SS:ESP? If so, I'm
still not sure what "restriction [related] to the usage of stack"
exactly means, so I've probably been unable to address the OP's intended
query. I might learn something from reading a response of yours to the
original post. Mr. James Kuyper doesn't exactly establish what he means
by "stack" and Mr. Xavier Roche gives a probable cause for the mudflap
violation.
Telling him that
"C doesn't have a stack", while strictly correct, is unlikely to be
helpful.

I disagree. In another C-devoted forum, the sooner people replace their
mental shortcuts with the C notions, the sooner they seem to be able to
correctly answer "fill-in-the-blank"-style questions. I gather that
your experiences here and possibly elsewhere have taught you otherwise,
so mileage must vary. :)
 
I

Ian Collins

Shao said:
I disagree, and don't know why you believe that's so. "C doesn't have a
stack" is supposed to remove a mistake. Here's one possible model for
the learning process:

Why didn't you just say "A C implementation doesn't require a stack"?
 
K

Keith Thompson

Shao Miller said:
Shao Miller said:
On 2/17/2013 16:18, Keith Thompson wrote:
On 2/14/2013 07:29, (e-mail address removed) wrote:
Is there any restriction releated to the
usage of stack in branches after longjmp ?

C doesn't have a stack.

That's an oversimplification.

It's true, as I've said many times myself, that the word "stack"
doesn't appear in the C standard. It's also true that a C
implementation needn't use a contiguous stack, and there are a few
that don't.

On the other hand, C function call semantics require some sort of
underlying last-in first-out data structure (whether it's implemented
as a contiguous growing memory stack or not) -- and the vast majority
of C implementations *do* use a contiguous memory stack.

[...]

One point that can be taken from what I said is: If you use a term
that's outside of the language, you might get responses where your
actual query is not addressed. "Restriction related to the usage of
stack": What does this mean? The list of called functions since 'main'?
All storage occupied by objects having automatic storage duration and
which have their addresses taken? "Stack" does not compute*.

Yes, that *can* be taken from what you said, but only by someone who
already understand the issues.

I disagree, and don't know why you believe that's so. "C doesn't have
a stack" is supposed to remove a mistake.
[snip]

And replace it with what?

The assumption that C requires a contiguous stack can lead to an
understanding that's correct for most implementations. Saying "C
doesn't have a stack" with no further information is likely to
be unhelpful.

[...]
What is an example of the conventional sense? x86' SS:ESP?

Probably. (I know what the x86 is, but I'm unclear on "SS:ESP";
is that the stack pointer register?).
If so,
I'm still not sure what "restriction [related] to the usage of stack"
exactly means, so I've probably been unable to address the OP's
intended query. I might learn something from reading a response of
yours to the original post. Mr. James Kuyper doesn't exactly
establish what he means by "stack" and Mr. Xavier Roche gives a
probable cause for the mudflap violation.

I don't actually have an answer for the OP's question.

[...]
 
S

Shao Miller

Why didn't you just say "A C implementation doesn't require a stack"?

Why do I have to defend what I typed? In another C-devoted forum, this
is a pretty standard response and seems to work very nicely...
Eventually people start talking (and thinking) in C terms, and all is
well. Is your suggestion a working alternative? If so, then ok.
 
Ad

Advertisements

S

Shao Miller

Shao Miller said:
On 2/17/2013 16:18, Keith Thompson wrote:
On 2/14/2013 07:29, (e-mail address removed) wrote:
Is there any restriction releated to the
usage of stack in branches after longjmp ?

C doesn't have a stack.

That's an oversimplification.

It's true, as I've said many times myself, that the word "stack"
doesn't appear in the C standard. It's also true that a C
implementation needn't use a contiguous stack, and there are a few
that don't.

On the other hand, C function call semantics require some sort of
underlying last-in first-out data structure (whether it's implemented
as a contiguous growing memory stack or not) -- and the vast majority
of C implementations *do* use a contiguous memory stack.

[...]

One point that can be taken from what I said is: If you use a term
that's outside of the language, you might get responses where your
actual query is not addressed. "Restriction related to the usage of
stack": What does this mean? The list of called functions since 'main'?
All storage occupied by objects having automatic storage duration and
which have their addresses taken? "Stack" does not compute*.

Yes, that *can* be taken from what you said, but only by someone who
already understand the issues.

I disagree, and don't know why you believe that's so. "C doesn't have
a stack" is supposed to remove a mistake.
[snip]

And replace it with what?

Nothing. My crystal ball is at the repair shoppe, so Maciej Labanowicz
can clarify or discard, rather than my offering guesses. As it turns
out, Maciej Labanowicz hasn't responded to the thread at all, so instead
I'm spending time defending what I typed instead of finding out about
the impact of everyone's responses.
The assumption that C requires a contiguous stack can lead to an
understanding that's correct for most implementations. Saying "C
doesn't have a stack" with no further information is likely to
be unhelpful.

That's not quite the same as "unlikely to be helpful". Are you really
suggesting that it could be detrimental? I came from "all the world's
an x86" to [hopefully] better understanding portability by someone
telling me precisely this... It involved figuring out what to replace
the notion with.
[...]
What is an example of the conventional sense? x86' SS:ESP?

Probably. (I know what the x86 is, but I'm unclear on "SS:ESP";
is that the stack pointer register?).

I think so. I seem to recall that "SS" is a register for the "stack
segment" and "ESP" is a [32-bit version of the] register for the "stack
pointer".
 
K

Keith Thompson

Shao Miller said:
I disagree, and don't know why you believe that's so. "C doesn't have
a stack" is supposed to remove a mistake.
[snip]

And replace it with what?

Nothing. My crystal ball is at the repair shoppe, so Maciej Labanowicz
can clarify or discard, rather than my offering guesses. As it turns
out, Maciej Labanowicz hasn't responded to the thread at all, so instead
I'm spending time defending what I typed instead of finding out about
the impact of everyone's responses.
The assumption that C requires a contiguous stack can lead to an
understanding that's correct for most implementations. Saying "C
doesn't have a stack" with no further information is likely to
be unhelpful.

That's not quite the same as "unlikely to be helpful". Are you really
suggesting that it could be detrimental?

No distinction between "unlikely to be helpful" and "likely to be
unhelpful" was intended, and neither necessarily implies that it's
detrimental. I don't usually choose my words *quite* that carefully.
I came from "all the world's
an x86" to [hopefully] better understanding portability by someone
telling me precisely this... It involved figuring out what to replace
the notion with.

Did you figure it all out from the bare statement "C doesn't have a
stack", or did someone explain it to you?

In one sense C certainly does have a stack; objects with automatic
storage allocation and active function calls are both created and
destroyed in a last-in first-out manner.

[...]
 
I

Ian Collins

Shao said:
Why do I have to defend what I typed? In another C-devoted forum, this
is a pretty standard response and seems to work very nicely...
Eventually people start talking (and thinking) in C terms, and all is
well. Is your suggestion a working alternative? If so, then ok.

I suggest substituting "require" for "have" is clearer. C can have a
stack, but it doesn't require one.
 
K

Keith Thompson

Shao Miller said:
Why do I have to defend what I typed? In another C-devoted forum,
this is a pretty standard response and seems to work very
nicely... Eventually people start talking (and thinking) in C terms,
and all is well. Is your suggestion a working alternative? If so,
then ok.

Out of curiosity, what other C-devoted forum are you referring to?
 
Ad

Advertisements

S

Shao Miller

Shao Miller said:
I came from "all the world's
an x86" to [hopefully] better understanding portability by someone
telling me precisely this... It involved figuring out what to replace
the notion with.

Did you figure it all out from the bare statement "C doesn't have a
stack", or did someone explain it to you?

I don't quite remember, to be honest. The severity of the statement was
memorable, though. Turns out that folks in another C-devoted forum use
the same statement, a fair bit.
In one sense C certainly does have a stack; objects with automatic
storage allocation and active function calls are both created and
destroyed in a last-in first-out manner.

Sure. And when writing a Network Bootstrap Program in C, one considers
the PXE stack, too. I'd guess that the original poster was probably
talking about something more along the lines of your notion, though.
 
Ad

Advertisements

G

glen herrmannsfeldt

Keith Thompson said:
(snip)

(snip)

Did you figure it all out from the bare statement "C doesn't have a
stack", or did someone explain it to you?
In one sense C certainly does have a stack; objects with automatic
storage allocation and active function calls are both created and
destroyed in a last-in first-out manner.

The problem is that "stack" can have different meanings.

It can be logical (first-in first-out) or physical (a contiguous
array of memory with a stack pointer that can be updated).

As I did much programming (though not in C) with OS/360, I got
pretty used to the way OS/360 does things on a processor without
a stack pointer. The traditional OS/360 call sequence, still used
by z/OS, uses a doubly linked list.

If you are careful to separate the "logical" from "physical"
then yes, C has a stack. The description of PL/I CONTROLLED
variables is that they stack. If you allocate one, previous
allocations are stacked, and can be restored later. But no,
there is no contiguous data structure with stack pointer
used for such on OS/360.

If you do an interprocedure GOTO (using a LABEL variable) in
OS/360 PL/I, it has to deallocate all the DSAs (dynamic save
areas) in between.

-- glen
 

Top