全部博文(11)
分类: C/C++
2014-08-15 11:17:45
判断堆栈增长方向
在alloca.c中find_stack_direction函数,用来判断堆栈的增长方向,记录下来。
#define ADDRESS_FUNCTION(arg) &(arg)
/* Define STACK_DIRECTION if you know the direction of stack
growth for your system; otherwise it will be automatically
deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
#ifndef STACK_DIRECTION
#define STACK_DIRECTION 0 /* Direction unknown. */
#endif
#if STACK_DIRECTION != 0
#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
#else /* STACK_DIRECTION == 0; need run-time code. */
static int stack_dir; /* 1 or -1 once known. */
#define STACK_DIR stack_dir
static void
find_stack_direction ()
{
static char *addr = NULL; /* Address of first `dummy', once known. */
auto char dummy; /* To get stack address. */
if (addr == NULL)
{ /* Initial entry. */
addr = ADDRESS_FUNCTION (dummy);
find_stack_direction (); /* Recurse once. */
}
else
{
/* Second entry. */
if (ADDRESS_FUNCTION (dummy) > addr)
stack_dir = 1; /* Stack grew upward. */
else
stack_dir = -1; /* Stack grew downward. */
}
}
#endif /* STACK_DIRECTION == 0 */
find_stack_direction函数使用函数递归的方法
第一次进入,由于addr为NULL,所以将字符变量dummy的地址赋值给静态变量addr
第二次进入,由于静态变量addr已赋了值,所以进入 "Second entry."
接着,将第二次进入的dummy地址和第一次进入的dummy地址相比较
如果值为正,则堆栈向高地址增长;否则,堆栈向低地址增长
为什么要这么复杂呢,不能再一个函数里面写两个局部变量比较器地址大小来确定栈的方向?其实问题很简单,一个函数中的所有东西压入栈之后,其里面的
局部变量和参数变量的地址依赖于编译器,而,如果通过一个函数调用另外一个函数就能确保比较的地址不依赖与编译器了,其实一种做法是在一个函数中调用另外
一个函数,将调用函数中的局部变量地址传递到被调用函数中,和被调用函数中的局部变量的地址进行比较,如果大的话,则增长方向为由高地址向低地址生长,反
之则反,最好的方式是声明局部变量的时候声明为violate类型,这样才能确保编译器不去处理violate这个变量,而这篇文章中的方法非常巧妙
find_stack_direction函数使用函数递归的方法
第一次进入,由于addr为NULL,所以将字符变量dummy的地址赋值给静态变量addr
第二次进入,由于静态变量addr已赋了值,所以进入 "Second entry."
接着,将第二次进入的dummy地址和第一次进入的dummy地址相比较
如果值为正,则堆栈向高地址增长;否则,堆栈向低地址增长
巧妙地运用了“函数递归也使用了堆栈”的思想