1、为什么不能从函数中返回一个指向该函数局部自动变量的指针?(自动变量:函数返回时系统回收变量所占存储空间,一般的局部变量均是自动变量)
char * favorite_fruit ()
{
char deciduous [ ] ="apple";
return deciduous;
}
当进入该函数时,自动变量deciduous在堆栈中分配。当函数结束后,变量不复存在,它所占用的堆栈空间被回收,可能在任何时候被覆盖。这样,指针就失去了有效性(引用不存在的东西),被称为“悬垂指针”-----它们并不引用有用的东西,而是悬在地址空间内。如果想返回一个指向在函数内部定义的变量的指针时,要把那个变量声明为 static 。这样就能保证该变量被保存在数据段中而不是堆栈中。该变量的生命周期就和程序一样长,当定义该变量的函数退出时,该变量的值依然能保持,当该函数下一次进入时,该值依然有效。
2、过程活动记录可能并不位于堆栈中:
过程记录活动并不一定要存在与堆栈中。事实上尽可能地将过程活动记录的内容放到寄存器中会使函数调用的速度更快,效果更好。“寄存器窗口”,CPU拥有一组寄存器,它们只用于保存过程活动记录中的参数。每当函数调用时,空的活动记录依然压入到堆栈中。当函数调用链非常深而寄存器窗口不够用时,寄存器的内容就会保存到堆栈中保留的活动记录空间中,以便重新利用这些寄存器。
3、setjmp和longjmp(它们都是通过操纵过程活动记录实现的,头文件:#include <setjmp.h> )
setjmp(jmp_buf j)必须首先被调用。它表示“使用变量 j 记录现在的位置。函数返回零”
longjmp(jmp_buf j, int i)可以接着被调用。它表示“回到 j 所记录的位置,让它看上去像是从原先的 setjmp() 函数返回一样。但是函数返回 i ,使代码能够实际上是通过 longjmp() 返回的。”
例如:
#include <stdio.h>
#include <setjmp.h>
jmp_buf buf;
banana()
{
printf("in banana() \n");
longjmp(buf, 1);
printf("you' ll neversee this, because i longjmp'd ");
}
int main()
{
if (setjmp(buf) == 1)
{
printf("back in main \n");
}
else
{
printf("first time through \n");
banana();
}
}
结果如下:
first time through
in banana()
back in main
setjmp/longjmp 最大的用途是错误恢复。只要还没有从函数中返回,一旦发现一个不可恢复的错误,可以把控制转移到主输入循环,并从那里重新开始。
4、MS-DOS (微软磁盘操作系统)中的堆栈段
在DOS中,在建立可执行文件时,堆栈的大小必须同时确定,而且它不能在运行时增长。若需要的空间大于所分配的空间,程序和会迷失。
确定堆栈大小的方法根据所使用的不同编译器而不同。在Microsoft编译器中,程序员可以把堆栈的大小作为一个链接器参数来确定。
STACK: nnn
这个参数告诉Microsoft 链接器为堆栈分配nnn字节。
Borland 编译器则使用一个特殊的名字的变量:
unsigned int _stklen = 0x4000; /* 16k 堆栈 */