468,771 Members | 1,589 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,771 developers. It's quick & easy.

Detect direction of stack growth

Hi all,

Is this a (C99) portable way to detect whether the C stack grows upwards
(1) or downwards (-1)?

#include <stdio.h>

int stack_direction=0;

void detect_stack_direction(void * stack_start) {
void * stack_current;
stack_direction=-1;
if (&stack_start<&stack_current) stack_direction=1;
}

int main() {
void * stack_start;
detect_stack_direction(stack_start);

printf("Stack grows: %i\n", stack_direction);
return 0;
}

Thanks,
Adam
Nov 14 '05 #1
6 2302
Adam Warner <us****@consulting.net.nz> writes:
Is this a (C99) portable way to detect whether the C stack grows upwards
(1) or downwards (-1)?


No. There is no portable way to do this. Applying a relational
operator to addresses of distinct objects (objects that are not
contained in some larger composite object) invokes undefined behavior.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #2
Hi Keith Thompson,
Adam Warner <us****@consulting.net.nz> writes:
Is this a (C99) portable way to detect whether the C stack grows
upwards (1) or downwards (-1)?


No. There is no portable way to do this. Applying a relational
operator to addresses of distinct objects (objects that are not
contained in some larger composite object) invokes undefined behavior.


Can I cast the addresses of the objects on the stack to uint64_t
(7.18.1.1) and use a relational operator upon those values? This type
is defined for all conforming implementations with 64 bit integers.

What practically portable method exists to perform pointer arithmetic via
integers? Does one first perform an implementation-specific check upon the
size of the address space? Can I practically rely upon the address space
never being larger than 64 bits?

Thanks again,
Adam
Nov 14 '05 #3
"Adam Warner" <us****@consulting.net.nz> wrote in message
news:pa****************************@consulting.net .nz...
Hi Keith Thompson,
Adam Warner <us****@consulting.net.nz> writes:
Is this a (C99) portable way to detect whether the C stack grows
upwards (1) or downwards (-1)?
No. There is no portable way to do this. Applying a relational
operator to addresses of distinct objects (objects that are not
contained in some larger composite object) invokes undefined behavior.


Can I cast the addresses of the objects on the stack to uint64_t
(7.18.1.1) and use a relational operator upon those values? This type
is defined for all conforming implementations with 64 bit integers.


You cannot get any meaningful information. Stack management
is implementation dependent. Some implementations grow down,
some grow up, some are segmented, some grow in either direction.

Forget about it.
What practically portable method exists to perform pointer arithmetic via
integers?
Pointer arithmetic is only meaningful for addresses within a single object.
Does one first perform an implementation-specific check upon the
size of the address space?
A meaningless question.
Can I practically rely upon the address space
never being larger than 64 bits?


No. That presumes a linear address space. An address space
need not be linear. IBM mainframe architecture has non-linear
virtual spaces with 64-bit "addresses" and 25-bit "space designation".
Somewhat like trying to compare two complex numbers for greater-than
or less-than; non-sensical. Only equals or unequals has meaning when
comparing two objects that may not be the same object.

Nov 14 '05 #4
Adam Warner <us****@consulting.net.nz> writes:
Hi Keith Thompson,
Adam Warner <us****@consulting.net.nz> writes:
Is this a (C99) portable way to detect whether the C stack grows
upwards (1) or downwards (-1)?
No. There is no portable way to do this. Applying a relational
operator to addresses of distinct objects (objects that are not
contained in some larger composite object) invokes undefined behavior.


Can I cast the addresses of the objects on the stack to uint64_t
(7.18.1.1) and use a relational operator upon those values? This type
is defined for all conforming implementations with 64 bit integers.


It would make more sense to cast to intptr_t or uintptr_t (assuming a
C99 implementation), but these types aren't guaranteed to exist, and
even if they do they aren't guaranteed to behave the way you want them
to.
What practically portable method exists to perform pointer arithmetic via
integers?
None.
Does one first perform an implementation-specific check upon the
size of the address space? Can I practically rely upon the address space
never being larger than 64 bits?


Addresses can't necessarily be interpreted as integers. There has to
be some stack-like first-in last-out data structure to support nested
function calls, including recursion, but there's not necessarily any
particular ordering between objects corresponding to deeper and
shallower calls.

Relational operators ("<", "<=", ">", ">=") on pointers apply only
within an object. Otherwise, as far as the C standard is concerned,
there is no ordering relationship.

Of course there can be meaningful ordering of pointer values on many
implementations, but not all. I think IBM's AS/400 is an example of a
system that can support a conforming C implementation, but on which
pointers don't behave anything like what you might expect.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #5
In <ln************@nuthaus.mib.org> on Mon, 27 Dec 2004 09:39:06 +0000, Keith Thompson wrote:
X-Pan-Internal-Sendlater-Newsgroups: comp.lang.c
X-Pan-Internal-Post-Server: news.individual.net
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Hi Keith Thompson,

In <ln************@nuthaus.mib.org> on Mon, 27 Dec 2004 09:39:06 +0000,
Keith Thompson wrote:
Addresses can't necessarily be interpreted as integers. There has to
be some stack-like first-in last-out data structure to support nested
function calls, including recursion, but there's not necessarily any
particular ordering between objects corresponding to deeper and
shallower calls.

Relational operators ("<", "<=", ">", ">=") on pointers apply only
within an object. Otherwise, as far as the C standard is concerned,
there is no ordering relationship.

Of course there can be meaningful ordering of pointer values on many
implementations, but not all. I think IBM's AS/400 is an example of a
system that can support a conforming C implementation, but on which
pointers don't behave anything like what you might expect.


Thanks Keith! I was attempting to ascertain the extent of the stack so I
could check it for potential pointers to heap allocated objects in order
to implement a simple garbage collector. I still have one outstanding
concern that a live pointer to the heap might exist solely within a
CPU register.

But at this stage I'm far better off dropping in the Boehm-Demers-Weiser
garbage collector and tacking easier issues.

I'm really enjoying learning C. Thanks for your responses.

Regards,
Adam
Nov 14 '05 #6

"Adam Warner" <us****@consulting.net.nz> wrote

Thanks Keith! I was attempting to ascertain the extent of the stack so I
could check it for potential pointers to heap allocated objects in order
to implement a simple garbage collector. I still have one outstanding
concern that a live pointer to the heap might exist solely within a
CPU register.

But at this stage I'm far better off dropping in the Boehm-Demers-Weiser
garbage collector and tacking easier issues.

Garbage collection is inherently compiler-dependent.

If you want to investigate pointers, the portable way to do it is to print
out the value of the pointer usings the %p specifier. For most practical
purposes, this will tell you what stack management technique your compiler
uses. However be aware that a conforming compiler might do something really
unusual, such as splitting the stack into 16K segments and growing one
upwards and one downwards. Really you need to get the compiler documentation
to be sure you ar enot caught out.
Nov 14 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

reply views Thread by Dave Serrano | last post: by
23 posts views Thread by Michel Bany | last post: by
6 posts views Thread by Einar ?rn | last post: by
13 posts views Thread by Ben R. Bolton | last post: by
4 posts views Thread by Chris Johnson | last post: by
18 posts views Thread by junky_fellow | last post: by
reply views Thread by zhoujie | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.