How to know that stack is growing upward/downward?

N

Nitin Bhardwaj

Hi all,

I wanted to know whether the stack in a C program is growing upwards
or
downwards.So I wrote a little code to see that.Please guide me as to
whether this code is correct in telling this ?

#include <stdio.h>
int main(void)
{
int * buf1 = malloc(10 * sizeof(int));
int *buf2 = malloc(10*sizeof(int));

printf( buf1 ? buf2 ? "Downward" : "Backward");

return 0;
}

Thanks...
 
A

Ariane van der Steldt

I wanted to know whether the stack in a C program is growing upwards
or
downwards.So I wrote a little code to see that.Please guide me as to
whether this code is correct in telling this ?

#include <stdio.h>
int main(void)
{
int * buf1 = malloc(10 * sizeof(int));
int *buf2 = malloc(10*sizeof(int));

printf( buf1 ? buf2 ? "Downward" : "Backward");

return 0;
}

malloc et all don't allocate on the stack.
The direction of the stack is undefined in C. Refer to OS or hardware
specific documentation.

Ariane
 
R

Richard Tobin

Nitin Bhardwaj said:
I wanted to know whether the stack in a C program is growing upwards
or downwards. So I wrote a little code to see that.Please guide me as to
whether this code is correct in telling this ?
int * buf1 = malloc(10 * sizeof(int));
int *buf2 = malloc(10*sizeof(int));

printf( buf1 ? buf2 ? "Downward" : "Backward");

This shows you the order of two objects allocated on the heap (which is
likely not to be consistent). You need to compare the addresses of local
variables, e.g.

char *stack_dir(void)
{
int a;
return stack_dir_helper(&a);
}

char *stack_dir_helper(int *a)
{
int *b;
return b < a ? "down" : "up";
}

This is of course not theoretically portable, but is likely to work on all
machines where the answer would be useful.

The only program I recall seeing that needed to know the stack
direction was Doug Gwyn's "portable alloca".

-- Richard
 
E

Emmanuel Delahaye

Nitin Bhardwaj wrote on 02/08/04 :
I wanted to know whether the stack in a C program is growing upwards
or
downwards.

There is no standard way to determine that. The answer is on your
compiler's documentation.
 
P

pete

Richard Tobin wrote:
char *stack_dir_helper(int *a)
{
int *b;
return b < a ? "down" : "up";
}

This is of course not theoretically portable,

"Undefined behavior" is the term usually used
to describe code like that in this newsgroup.
but is likely to work on all
machines where the answer would be useful.

I doubt it.
Your code attempts to compare the value of a,
which is a passed in argument,
against the value of b,
which is an uninitialized variable with an indeterminate value.
 
R

Richard Tobin

char *stack_dir_helper(int *a)
{
int *b;
return b < a ? "down" : "up";
}
[/QUOTE]
Your code attempts to compare the value of a,
which is a passed in argument, against the value of b,
which is an uninitialized variable with an indeterminate value.

Oops, of course that should be

int b;
return &b < a ? "down" : "up";

(I even compiled and ran the original to check for mistakes, but some
mistakes still produce the expected output!)

-- Richard
 
J

Jens.Toerring

Richard Tobin said:
Oops, of course that should be
int b;
return &b < a ? "down" : "up";
(I even compiled and ran the original to check for mistakes, but some
mistakes still produce the expected output!)

The standard still tells you explicitely that you invoke undefined
behavior here, because 'a' and '&b' aren't pointers to members of
the same aggregate or union object (or one points to an array element
and the other points to the element directly after the same array).
Moreover, nothing forces the compiler to use a stack at all. So this
"solution" is about as safe as telling someone asking how to find
out the sequence in which function arguments are evaluated to use

int i = 0;
printf( "%d %d\n", ++i, ++i );

Regards, Jens
 
R

Richard Tobin

The standard still tells you explicitely that you invoke undefined
behavior here, because 'a' and '&b' aren't pointers to members of
the same aggregate or union object (or one points to an array element
and the other points to the element directly after the same array).
Moreover, nothing forces the compiler to use a stack at all.

We all know that. If you've got nothing useful to say, stay silent.

I imagine someone coming up to you in the street, and asking the way
to the post office. Instead of telling them, you point out that
there's no guarantee that there is a port office in this town, and
tell them that asking a stranger might lead to undefined behaviour.

There seems to be something about this newsgroup which produces an
almost religious unhelpfulness. It never used to be like that.

*If* your C implementation uses a stack - and if you say yours
doesn't, you're probably lying - then the code I gave will tell you
which way it goes. There are several reasons for wanting to know,
one of which I gave as an example, and another of which is just an
interest in how your machine works.

-- Richard
 
J

Jens.Toerring

Richard Tobin said:
We all know that. If you've got nothing useful to say, stay silent.

Are you sure? Ask the OP if he knows about that restriction. I for
one didn't know about such things at all when I learned C by myself
and only became aware of such problems by reading this newsgroup
_because_ people pointed them out again and again.
I imagine someone coming up to you in the street, and asking the way
to the post office. Instead of telling them, you point out that
there's no guarantee that there is a port office in this town, and
tell them that asking a stranger might lead to undefined behaviour.

Well, what you were telling the OP was: "Drive through that one-way
road to the post office." and not even mention that there's a the
big, fat sign that forbids to drive in that direction.
There seems to be something about this newsgroup which produces an
almost religious unhelpfulness. It never used to be like that.

Why is pointing out that the results of that operation can give
you completely wrong results unhelpful? The compiler is free to
produce code that exactly does what you expect it to do but it's
equally free to produce code that results in output that says the
stack is growing upwards while in reality its growing downward. And
it also is allowed to produce code that reformats the hard disk...

As far as I know this group it was standard to point out such
potential problems carefully. And I for one would like it to
stay it that way because otherwise whatever I read here would
have be taken with too much a grain of salt to be useful anymore.
*If* your C implementation uses a stack - and if you say yours
doesn't, you're probably lying - then the code I gave will tell you
which way it goes. There are several reasons for wanting to know,
one of which I gave as an example, and another of which is just an
interest in how your machine works.

Wanting to know is completely legitimate. But proposing methods to
find out that are not guaranteed to work without pointing out the
possible pitfalls isn't that helpful in my book.

Regards, Jens
 
A

Arthur J. O'Dwyer

The standard still tells you explicitely that you invoke undefined
behavior here, because 'a' and '&b' aren't pointers to members of
the same aggregate or union object (or one points to an array element
and the other points to the element directly after the same array).
Moreover, nothing forces the compiler to use a stack at all.

We all know that. If you've got nothing useful to say, stay silent.

I imagine someone coming up to you in the street, and asking the way
to the post office. Instead of telling them, you point out that
there's no guarantee that there is a [post] office in this town, and
tell them that asking a stranger might lead to undefined behaviour.

Well, that would be false --- in general, asking a stranger does
/not/ lead to undefined behavior. :) Jens' response, while less
helpful than it could have been,[1] was right on the money.

-Arthur

[1] - For example, Jens could have explicitly pointed out that
where your code had

you almost certainly meant to write

which will "correctly" return "down" on common unoptimized Wintel
implementations. I have no idea what it will produce for the average
'gcc -O2', in which it is common for both 'a' and 'b' to be stored
in 80x86 machine registers, let alone on a different architecture
entirely!
 
J

Jens.Toerring

Arthur J. O'Dwyer said:
The standard still tells you explicitely that you invoke undefined
behavior here, because 'a' and '&b' aren't pointers to members of
the same aggregate or union object (or one points to an array element
and the other points to the element directly after the same array).
Moreover, nothing forces the compiler to use a stack at all.

We all know that. If you've got nothing useful to say, stay silent.

I imagine someone coming up to you in the street, and asking the way
to the post office. Instead of telling them, you point out that
there's no guarantee that there is a [post] office in this town, and
tell them that asking a stranger might lead to undefined behaviour.
Well, that would be false --- in general, asking a stranger does
/not/ lead to undefined behavior. :) Jens' response, while less
helpful than it could have been,[1] was right on the money.
[1] - For example, Jens could have explicitly pointed out that
where your code had
you almost certainly meant to write


Not necessarily, if it works as advertised it will probably work with
both methods. In the first version 'a' is an automatic variable in an
earlier stack frame, so it should have a lower or higher address than
'b', depending on in which direction the stack grows (just with a
larger offset).
which will "correctly" return "down" on common unoptimized Wintel
implementations. I have no idea what it will produce for the average
'gcc -O2', in which it is common for both 'a' and 'b' to be stored
in 80x86 machine registers, let alone on a different architecture
entirely!

gcc puts all variables that have their address taken into memory
and not keep them in registers (AFAIK even variables with storage
class register).
Regards, Jens
 
C

Christian Bau

Why is pointing out that the results of that operation can give
you completely wrong results unhelpful? The compiler is free to
produce code that exactly does what you expect it to do but it's
equally free to produce code that results in output that says the
stack is growing upwards while in reality its growing downward. And
it also is allowed to produce code that reformats the hard disk...

Anyway, there is very little consensus what the "top" and the "bottom"
of memory mean. While many people think that it is obvious, they don't
quite agree which of the two obvious possibilities they mean.

Much better to use the terms "left to right" or "right to left".
 
C

Chris Torek

*If* your C implementation uses a stack - and if you say yours
doesn't, you're probably lying - then the code I gave will tell you
which way it goes.

Except, perhaps, where it may not. For instance, imagine an old
8086 compiler that uses the at-most-65536-byte segments (as quite
a few did) but changes the value in SS (the 'stack segment' pointer)
at the entry to each new function, so that each stack frame has
the full 64K available. Here the "sp" register in effect is always
zero. The result of &a is something like <xxxx:0> while &b is
something like <yyyy:0>. Equality comparisons (&a == &b, &a !=
&b) compare both segment-and-offset and say "not equal", but
relational comparisons (&a < &b) compare only offsets, giving the
wrong answer.

Of course, a real 8086 compiler would have to do extra work here
(because CALL and RET adjust SP, so every function entry would
have to recompute both SS and SP, and function exit would have to
undo this work) so this kind of implementation is unlikely on the
8086 -- but there might be other machines with similar oddities.
Since the C standard says that the effect of comparing pointers
that are not "pointing into" the same object (or one past the end
of that object) is undefined, an implementor is free -- at least
as far as C89 and C99 are concerned -- to do this sort of thing.

This does not mean you cannot experiment with whatever implementations
you have lying around, but it does mean you cannot extrapolate from
the results without some sort of additional information.
 
D

Dik T. Winter

>
> Are you sure? Ask the OP if he knows about that restriction. I for
> one didn't know about such things at all when I learned C by myself
> and only became aware of such problems by reading this newsgroup
> _because_ people pointed them out again and again.

But Richard explicitly mentions in his first article on this subject that
his solution is not technically portable, so what more do you want? And
indeed, it will not port to all systems, but will port to many. (And I
have used a machine to which it would not port.)
> Well, what you were telling the OP was: "Drive through that one-way
> road to the post office." and not even mention that there's a the
> big, fat sign that forbids to drive in that direction.

But he *did* mention it.

And here Richard is wrong... I know of at least one machine where for
each call to a routine a new memory segment was started. I do not know
whether comparison between addresses from different segments was useful,
or even allowed, but I would hesitate to port his solution to that
machine.
 
R

Richard Tobin

Well, what you were telling the OP was: "Drive through that one-way
road to the post office." and not even mention that there's a the
big, fat sign that forbids to drive in that direction.

You obviously missed where I said:

This is of course not theoretically portable, but is likely to work
on all machines where the answer would be useful.

-- Richard
 
J

Jack Klein

On 2 Aug 2004 22:01:00 GMT, (e-mail address removed) (Richard Tobin)
wrote in comp.lang.c:

[snip]
*If* your C implementation uses a stack - and if you say yours
doesn't, you're probably lying

[snip]

It just so happens that I frequently use an excellent compiler for a
popular microcontroller, and automatic variables are _NEVER_ allocated
on a stack.

BTW, *plonk* for the accusation.
 
D

Dik T. Winter

>
> you almost certainly meant to write ....

Almost certainly *not*. While the changed code may work on most
implementations, it will *not* work if parameter frames are put on
a place quite different from the standard stack. "a" is the address
of the original on the stack, "&a" is the address of the place where
that address is put to be passed as parameter.
 
A

Alex Fraser

[snip]
Anyway, there is very little consensus what the "top" and the "bottom"
of memory mean. While many people think that it is obvious, they don't
quite agree which of the two obvious possibilities they mean.


What are the two possibilities?
Much better to use the terms "left to right" or "right to left".

How does that help?

Alex
 
R

Richard Bos

I wanted to know whether the stack in a C program is growing upwards
or downwards.

Many people have been telling you that you can't do this, and that if
you assume a bog-standard OS you might be able to do this after all, and
that the results you might get are not necessarily meaningful, but
nobody has asked what I consider the most important question: _why_ do
you want to know this?
If it's simple curiosity, well and good, but if you think you really
need to know this in order to write good C, you are most likely better
off not knowing. Relying on system-dependent details like this is a
great way to make your code not only unportable, but unmaintainable and
probably more buggy than ordinary code.

Richard
 
C

Christian Bau

"Alex Fraser said:
[snip]
Anyway, there is very little consensus what the "top" and the "bottom"
of memory mean. While many people think that it is obvious, they don't
quite agree which of the two obvious possibilities they mean.


What are the two possibilities?

Can you think of _one_ possibility? If you say that a stack grows
"upward" or "downward" you must be able to say what that means, right?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top