Detect direction of stack growth

A

Adam Warner

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
 
K

Keith Thompson

Adam Warner said:
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.
 
A

Adam Warner

Hi Keith Thompson,
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
 
X

xarax

Adam Warner said:
Hi Keith Thompson,


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.
 
K

Keith Thompson

Adam Warner said:
Hi Keith Thompson,

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.
 
A

Adam Warner

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 said:
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
 
M

Malcolm

Adam Warner said:
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.
 

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,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top