Writing a function to figure out if stack grows up or down

S

sacindia2000

Hi,
I came across a question which talks of writing a function to figure
out if stack grows up or down.
I wrote the following function :

void StackGrowth(void)
{
int a=20;
int b=10;
if(&a > &b)
printf("STACK growth from bottom to top 1st %x 2nd %x",&a,&b);
else
printf("STACK growth from Top to Bottom 1st %x 2nd %x",&a,&b);


}

Is the above mentioned program processor and compiler independent?

Thanks
Sac
 
M

Michael Angelo Ravera

Hi,
  I came across a question which talks of writing a function to figure
out if stack grows up or down.
  I wrote the following function :

 void StackGrowth(void)
{
    int a=20;
    int b=10;
    if(&a > &b)
    printf("STACK growth from bottom to top 1st %x 2nd %x",&a,&b);
    else
    printf("STACK growth from Top to Bottom 1st %x 2nd %x",&a,&b);

}

Is the above mentioned program processor and compiler independent?


The code you have here is compiler dependant (and also uses some
nonstandard or undefined features).

It is completely possible for a compiler allocate specific stack space
for each function and run the allocation backwards to the order in
which the variables are declared.

So, in order reliably to determine which way the stack grows, you will
need to call a function that uses the address of a variable in the
calling function and then determine whether the address of the
variable in the called function is less than or more than that of the
calling function.

You can probably do it the opposite way by having the called function
return the address of the variable in locals, but there are some
compilers that deliberately prevent this (for good reason).
 
S

Stephen Sprunk

Hi,
I came across a question which talks of writing a function to figure
out if stack grows up or down.
I wrote the following function :

void StackGrowth(void)
{
int a=20;
int b=10;
if(&a > &b)
printf("STACK growth from bottom to top 1st %x 2nd %x",&a,&b);
else
printf("STACK growth from Top to Bottom 1st %x 2nd %x",&a,&b);
}

Is the above mentioned program processor and compiler independent?

No. This will work probably better, and eliminates several problems in
your code:

/* not tested */
#include <stdio.h>

void check_stack(void *p)
{
int bar;
void *q = &bar;
printf("p = %p, q = %p\n", p, q);
printf("The stack grows %s.\n", (p<q) ? "up" : "down");
}

int main()
{
int foo;
check_stack(&foo);
return 0;
}

However, the comparison between p and q is still undefined. Moreover,
there is no guarantee that the implementation has a stack at all or that
it only grows in one direction, in which case your question is moot.

S
 
G

gw7rib

On 7 Jan, 21:53, (e-mail address removed) (Gordon Burditt) wrote:

Gordon seems to have lost the attribution lines. >> is Stephen Sprunk
and >>> is sacindia2000.
(snip)




This has the same problem:  it does not GROW the stack (if there
is a hardware stack), you need to call a function (any function)
for that.  There is no guarantee that auto variables will (or won't)
be allocated in alphabetical order by variable name.  (Or, for that
matter, allocated in a way that provides minimum alignment padding
required.)

No, I think Stephen is right. The stack grows when check_stack is
called. p is &foo, a local variable in main, whereas q is &bar, a
local variable in check_stack.
 
K

Keith Thompson

On 7 Jan, 21:53, (e-mail address removed) (Gordon Burditt) wrote:

Gordon seems to have lost the attribution lines. >> is Stephen Sprunk
and >>> is sacindia2000.

Gordon doesn't "lose" attribution lines. He deliberately deletes them.

[...]

Stephen said:
No, I think Stephen is right. The stack grows when check_stack is
called. p is &foo, a local variable in main, whereas q is &bar, a
local variable in check_stack.

You say Stephen is right, and then you contradict what he said. The
standard doesn't guarantee that there's such a thing as "the stack".
Function calls imply a stack-like data structure of some kind, in the
sense that things are allocated and deallocated in a last-in first-out
manner. But there's no guarantee, or even implication, that these
allocations occur contiguously or in a consistent direction. And no
portable program can even test this, since any relational comparison
between two pointers to distinct objects (that are not part of some
containing object) invokes undefined behavior.

Having said that, *most* C implementations do use a contiguous stack
that grows in a particular direction within a linear address space,
and *most* C implementations implement pointer comparison in a way
that reflects this linear address space. So at least some of the
programs that have been posted in this thread (though not the original
one) can be used to determine the direction in which "the stack"
grows. If you have a need for this information, and you don't mind
your program not being portable to the minority of implementations
that don't behave this way, then you can probably use the techniques
presented here.

But if you think you need this information (other than out of simple
curiosity), you're probably mistaken. There may be valid reasons for
a program to need to know which way the stack grows, but off the top
of my head I can't think of any.

[Permission to quote this article without proper attribution is
expressly denied.]
 
R

Richard Tobin

I came across a question which talks of writing a function to figure
out if stack grows up or down.
I wrote the following function :

void StackGrowth(void)
{
int a=20;
int b=10;
if(&a > &b)
printf("STACK growth from bottom to top 1st %x 2nd %x",&a,&b);
else
printf("STACK growth from Top to Bottom 1st %x 2nd %x",&a,&b);


}

Is the above mentioned program processor and compiler independent?

(a) No, you're not allowed to compare pointers to unrelated objects
(except for equality).
(b) Even if comparing them works, the local variables within a
function may not be allocated on the stack in any particular order
since they are all (conceptually) allocated at once.
(c) Look for Doug Gwyns's "portable alloca()", which attempts to
determine the direction of stack growth.

-- Richard
 
R

Richard

Keith Thompson said:
On 7 Jan, 21:53, (e-mail address removed) (Gordon Burditt) wrote:

Gordon seems to have lost the attribution lines. >> is Stephen Sprunk
and >>> is sacindia2000.

Gordon doesn't "lose" attribution lines. He deliberately deletes them.

[...]

Stephen said:
No, I think Stephen is right. The stack grows when check_stack is
called. p is &foo, a local variable in main, whereas q is &bar, a
local variable in check_stack.

You say Stephen is right, and then you contradict what he said. The
standard doesn't guarantee that there's such a thing as "the stack".
Function calls imply a stack-like data structure of some kind, in the
sense that things are allocated and deallocated in a last-in first-out
manner. But there's no guarantee, or even implication, that these
allocations occur contiguously or in a consistent direction. And no

But meanwhile in the real world where these people are coming from and
come here for help in ....
 
R

Richard

Richard said:
It most certainly is.

Whoops, hit send too quickly there... It was going to be a bad joke
anyway. But here goes anyway and just to add a little more than the
curt, rude and thoroughly obnoxious Chuck Falconer:

To The OP:

The program is of course independent. The output, however, the same as
the compiled and linked binary is not ....
 
A

Antoninus Twink

(c) Look for Doug Gwyns's "portable alloca()", which attempts to
determine the direction of stack growth.

I don't know how it compares, but there's an in-built autoconf function
for this (in /usr/share/autoconf/autoconf/functions.m4), which
presumably has been written to be portable across many implementations.
It's very slightly tricksier than what the OP was doing, so probably
there's some subtlety somewhere on some systems.


int
find_stack_direction ()
{
static char *addr = 0;
auto char dummy;
if (addr == 0)
{
addr = &dummy;
return find_stack_direction ();
}
else
return (&dummy > addr) ? 1 : -1;
}


Interpretation:

if > 0 then grows toward higher addresses
if < 0 then grows toward lower addresses
if = 0 then direction of growth unknown
 
R

Richard

Keith Thompson said:
It most certainly is not. Explanation available on request.

You know you saw my instant follow up where I explained what I meant and
why I was being petty and jobsworth.
 
K

Keith Thompson

Richard said:
You know you saw my instant follow up where I explained what I meant and
why I was being petty and jobsworth.

I saw it only after I posted my followup.
 
S

Stephen Sprunk

Gordon said:
This does not GROW the stack (if there is a hardware stack), and
there is no guarantee that auto variables will (or won't) be allocated
in alphabetical order by variable name.
Correct.

One approach to GROW the stack would be to call a function which
returns the address of its auto variable (the compiler should
complain LOUDLY about this, but I don't think it involves undefined
behavior if the pointer returned is never dereferenced). Then
compare it to the address of the variable in the caller. That
comparison still causes undefined behavior. It also compares
addresses in different stack frames, which eliminates the issue
of how variables are ordered within a given stack frame.

Note that this could cause erratic results in the case of a function
that uses a linked list of save areas allocated with GETMAIN (see
OS/360 MVS linkage conventions). There's no telling whether the
next-allocated area will be higher or lower in address from the
current one.

I addressed that in the message you replied to.
This has the same problem: it does not GROW the stack (if there
is a hardware stack), you need to call a function (any function)
for that. There is no guarantee that auto variables will (or won't)
be allocated in alphabetical order by variable name. (Or, for that
matter, allocated in a way that provides minimum alignment padding
required.)

Look closer and you'll see that's exactly what I did, except that I
didn't invoke undefined behavior a second time by returning the address
of an auto variable and then examining it, as your example did.
Let's see: stack grows north for integer auto variables, east for
floating point variables, and up for pointers. Has anyone tried that?

As I said, in that case, the question is moot.

You really ought to read what you're replying to.

S
 
R

Richard

don't be daft. read the rest of the thread.

Suggestion you and some other regs who are too swift : read the thread
you reply to. You know I posted an addendum.
 
A

Amandil

No.  This will work probably better, and eliminates several problems in
your code:

/* not tested */
#include <stdio.h>

void check_stack(void *p)
{
     int bar;
     void *q = &bar;
     printf("p = %p, q = %p\n", p, q);
     printf("The stack grows %s.\n", (p<q) ? "up" : "down");

}

int main()
{
     int foo;
     check_stack(&foo);
     return 0;

}

However, the comparison between p and q is still undefined.  Moreover,
there is no guarantee that the implementation has a stack at all or that
it only grows in one direction, in which case your question is moot.

S

If the only problem - and it is the only one - is the comparison
between p and q, they can simply both be displayed to the user, with
the first printf, forget about the comparison, and let the user use
his own eyes and brains to figure it out. If you want to automate it
for use in alloca() or something like that, then you got a problem.

-- Marty Amandil
"In the beginning, the universe was created. This has been regarded by
many as a Bad Idea"
 
G

gw7rib

Keith [I presume you are the real one!] - there seems to have been a
bit of a mis-understanding. Possibly caused by the fact that I put my
comments after the end of the program, which meant they were spaced a
bit from Gordon's comments to which I was replying.
On 7 Jan, 21:53, (e-mail address removed) (Gordon Burditt) wrote:
Gordon seems to have lost the attribution lines. >> is Stephen Sprunk
and >>> is sacindia2000.

Gordon doesn't "lose" attribution lines.  He deliberately deletes them.

[...]

No, I think Stephen is right. The stack grows when check_stack is
called. p is &foo, a local variable in main, whereas q is &bar, a
local variable in check_stack.

You say Stephen is right, and then you contradict what he said.  The
standard doesn't guarantee that there's such a thing as "the stack".

Stephen said (in the passage quoted above) that there's no guarantee
that there even is a stack. I totally agree. I quoted the paragraph
purely because the program he offers assumes that there is, and I
didn't want to mis-lead by suggesting that he thought his program
would work under all circumstances.
Function calls imply a stack-like data structure of some kind, in the
sense that things are allocated and deallocated in a last-in first-out
manner.  But there's no guarantee, or even implication, that these
allocations occur contiguously or in a consistent direction.  And no
portable program can even test this, since any relational comparison
between two pointers to distinct objects (that are not part of some
containing object) invokes undefined behavior.

Having said that, *most* C implementations do use a contiguous stack
that grows in a particular direction within a linear address space,
and *most* C implementations implement pointer comparison in a way
that reflects this linear address space.  So at least some of the
programs that have been posted in this thread (though not the original
one) can be used to determine the direction in which "the stack"
grows.

Yes. Exactly. The OP posted a program that, even if you make
reasonable assumptions, will not necessarily work, because it depends
on which order the program puts variables of the same routine on the
stack. Stephen pointed out this mistake, and offered a program (which
he included with the usual caveats) which would, given certain
reasonable assumptions, detect whether the stack grew up or down. It
compared the addresses of a local variable in main with a local
variable of a called function check_stack. ("Local" should I think
strictly be called "automatic".)

Gordon replied to Stephen's post, critising both the OP's program and
Stephen's. While the criticism of the OP's program looked correct,
that of Stephen's program looked wrong and I explained why. I was not
trying to suggest that Stephen's program would work in all
circumstances - it won't, and he didn't claim it would - but it
avoided the flaw that Gordon had supposedly identified in it.

Hope this is clear now.

Paul.
 
K

Keith Thompson

Keith [I presume you are the real one!]
Yes.

there seems to have been a
bit of a mis-understanding. Possibly caused by the fact that I put my
comments after the end of the program, which meant they were spaced a
bit from Gordon's comments to which I was replying.

[big snip]
Yes. Exactly. The OP posted a program that, even if you make
reasonable assumptions, will not necessarily work, because it depends
on which order the program puts variables of the same routine on the
stack. Stephen pointed out this mistake, and offered a program (which
he included with the usual caveats) which would, given certain
reasonable assumptions, detect whether the stack grew up or down. It
compared the addresses of a local variable in main with a local
variable of a called function check_stack. ("Local" should I think
strictly be called "automatic".)

Gordon replied to Stephen's post, critising both the OP's program and
Stephen's. While the criticism of the OP's program looked correct,
that of Stephen's program looked wrong and I explained why. I was not
trying to suggest that Stephen's program would work in all
circumstances - it won't, and he didn't claim it would - but it
avoided the flaw that Gordon had supposedly identified in it.

Hope this is clear now.

Yes, thanks.
 
C

Chris M. Thomasson

Hi,
I came across a question which talks of writing a function to figure
out if stack grows up or down.
I wrote the following function :

void StackGrowth(void)
{
int a=20;
int b=10;
if(&a > &b)
printf("STACK growth from bottom to top 1st %x 2nd %x",&a,&b);
else
printf("STACK growth from Top to Bottom 1st %x 2nd %x",&a,&b);


}

Is the above mentioned program processor and compiler independent?

I guess you could try something like:
_________________________________________________________________________
#include <stdio.h>


static int
stack_direction_sys_check(
char const* const caller
) {
char const self[1];
printf("caller == (%p) - check == (%p)\n", (void*)caller, (void*)self);
return (self > caller);
}


static int
stack_direction(void) {
char const self[1];
return stack_direction_sys_check(self);
}


int main(void) {
if (stack_direction()) {
puts("stack seems to grow from top to bottom");
} else {
puts("stack seems to grow from bottom to top");
}
return 0;
}
_________________________________________________________________________




Its still not portable in any way shape or from. Oh well...
 

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,755
Messages
2,569,537
Members
45,023
Latest member
websitedesig25

Latest Threads

Top