函数中所有局部变量内容,函数参数的值,表明在调用函数的何处重新开始的返回地址。包含这些信息的数据区称为活动记录(activation record)或者栈框架(stack frame),位于运行时栈,只要函数在执行,其活动记录就一直存在。这个记录是函数的私有信息池,存储了程序正确执行并正确返回到调用它的函数所需要的所有信息。stack frame一般寿命很短,因为活动记录在函数开始执行时,得到动态分配的空间,在函数退出时释放其空间。主函数main()的活动记录的寿命比其他活动记录长。Stackframe通常包含以下信息:
1. 函数所有参数的值;如果传递的是数组或按引用传递变量,则活动记录包含该数组的第一个单元的地址或者该变量的地址;其他所有数据项的副本。
2. 可以存储在其他地方的局部变量,活动记录只包含他们的描述符以及指向其存放位置的指针。
3. 使得调用者重新获得控制权的返回地址,调用者指令的地址紧随这个调用之后。
4. 一个指向调用程序活动记录的指针,这是一个动态链接。
5. 非void类型的函数返回值。活动记录的空间大小随调用的不同而不同,返回值放在调用程序活动记录的正上方。
无论函数由主函数main()还是其它函数调用,都会在运行时栈中创建活动记录。运行时栈总是反应函数的当前状态。假定,主函数main()调用函数f1(),f1()调用f2(),f2()调用f3()。如果函数f3(),正在运行,运行时栈状态如下图。根据栈的特性,如果将栈指针移到紧挨着函数f3()返回值的下方,f3()的活动记录从栈中弹出,然后函数f2()继续执行,并能自由访问该函数重新执行所需的私有信息池。另外,如果f3()调用了另一个函数f4(),运行时栈空间增大,因为f4()的活动记录在该栈上创建,而f3(),将暂停执行。
无论什么时候调用函数,都会创建活动记录,这使得系统可以正确处理递归。递归只是被调用函数的名称正好和调用者相同。因此,递归调用,不是表面上的函数调用自身,而是一个函数的实例调用同一个函数的另一个实例。这些调用在内部表示为不同的活动记录,并由系统区分。——《C++数据结构与算法P138》