#include<cstdio>
#include<cstdlib>
#include<iostream>
using std::cout;
static void find_stack_direction(void);
static int stack_dir;
static void stack_growth_v1(void)
{
static char *addr = NULL; /* address of first`dummy', once known */
auto char dummy; /* to get stack address */
if (addr == NULL)
{ /* initial entry */
addr = &dummy;
stack_growth_v1 (); /* recurse once */
}
else if (&dummy > addr)/* second entry */
stack_dir = 1; /* stack grew upward */
else
stack_dir = -1; /* stack grew downward */
}
void stack_growth_v2(char *function_parameter)
{
char local;
if (&local > function_parameter)
printf("up\n");
else
printf("down\n");
}
void stack_growth_v3(volatile char *function_parameter)
{
volatile char local [64];
if (&local [63] > function_parameter)
printf("up\n");
else
printf("down\n");
}
void stack_growth_v4()
{
char *m1 = (char *)malloc(2);
char *m2 = (char *)malloc(2);
if (m2 > m1)
printf("down\n");
else
printf("up\n");
}
int main(void)
{
cout<<"---------stack_growth_v1----\n";
stack_growth_v1();
if(stack_dir==1)
puts("stack grew upward");
else
puts("stack grew downward");
cout<<"---------stack_growth_v2----\n";
char c = 'c';
stack_growth_v2(&c);
cout<<"---------stack_growth_3----\n";
volatile char d[64];
stack_growth_v3(&d[63]);
cout<<"---------stack_growth_4----\n";
stack_growth_v4();
return 0;
}
/***********************
运行结果:
---------stack_growth_v1----
stack grew downward
---------stack_growth_v2----
down
---------stack_growth_3----
down
---------stack_growth_4----
down
Process returned 0 (0x0) execution time : 0.640 s
Press any key to continue.
************************/
A simple way to determine the direction of stack growth is to compare the address of a function parameter with the address of a local variable in the function. Of course, the main difficulty here is to avoid compiler optimization, such as register variables, function inlining, and so on. So, the first attempt may look like the following function:
void stack_growth(char *function_parameter) {
char local;
if (&local > function_parameter)
printf("up\n");
else
printf("down\n");
}
The above code can be called as follows:
char c = 'c'; stack_growth(&c);
This example can be improved by using volatile modifiers and changing scalar variables into arrays:
void stack_growth(volatile char *function_parameter) {
volatile char local [64];
if (&local [63] > function_parameter)
printf("up\n");
else
printf("down\n");
}
and calling this function as follows:
volatile char c[64]; stack_growth(&c[63]);
It is also possible to find out the direction of stack growth by noting that it is the opposite of the heap growth direction (stack and heap usually grow towards each other), but this method is not very reliable either. For example, take the following code:
char *m1 = (char *)malloc(2);
char *m2 = (char *)malloc(2);
Whether m1 will be greater than m2 or not depends heavily on the memory allocation method.