• C专家编程 第6章 运行的诗章:运行时数据结构 6.5 当函数被调用时发生了什么:过程活动记录


    /*当函数被调用时发生了什么:过程活动记录*/

     

    C运行时系统在它自己的地址空间内如何管理程序。
    事实上,C语言的运行时函数非常少,但各个短小精悍。相反的例子是Ada或C++。

    如果C程序需要一些服务(如动态内存分配),它通常必须进行显示请求。这使C成为一种非常高效的语言。但它也向程序员施加了一个额外的负担。 

    C语言自动提供的服务之一就是跟踪调用链---那些函数调用了那些函数,以及当一个return语句执行后,控制将返回何处等。解决这个问题的经典机制就是堆栈中的过程活动记录。当每个函数被调用时,都会产生一个过程活动记录(或类似的结构)。过程活动记录是一种数据结构,用于支持过程调用,并记录调用结束以后返回调用点所需要的全部信息。

    局部变量(local variable)
    参数(argument)
    静态链接(static link)(用于上层引用,C语言不使用) 
    指向先前结构的指针
    返回地址(return address) 
                  图6-4 过程活动记录的规范描述
                  
    活动记录内容很具有说明性。结构的具体细节在不同的编译器中各有不同,这些字段的次序可能很不相同,而且可能存在一个在调用函数前保存寄存器值的区域。头文件/usr/include/sys/frame.h描述了过程活动记录就在UNIX系统中的样子。在SPARC计算机上,过程活动记录非常大(几十个字),因为它提供了保存寄存器窗口的空间。在x86架构中,过程活动记录多少要小一些。运行时系统维护一个指针(常常位于寄存器中),通常称为fp,用于提示活动堆栈结构,它的值是最靠近堆栈顶部的过程活动记录的地址。

    绝大多数的现代算法语言允许函数(以及数据)在函数内部定义。C语言不允许以这种方式进行函数的嵌套。C语言中的所有函数在词法层次中都是位于最顶层。 

    Pascal、Ada、Modula-2、PL/I或Algol-60这些允许嵌套过程的语言中,活动记录一般要包含一个指向它的外层函数的活动记录的指针。这个指针被称为静态链接(static link),它允许 内层过程访问外层过程的活动记录。因此也可以访问外层数据的局部数据。在同一时刻,一个外层过程可能有好几个处于活动状态的调用。内层过程活动记录的静态链接将指向合适的活动记录,允许访问局部数据的正确实例。

    这种类型的访问(一个指向词法上外层范围的数据项的引用)被称为上层引用(uplever reference)。静态链接(指向词法上将属于外层过程的活动记录,由编译时决定)之所以如此命名是因为它与动态链接相对照,后者是一个活动记录指针链(在运行时指向最靠近自己的前一个过程调用的活动记录)。

    C语言本身并不允许嵌套函数。因此,在它的数据中并没有上层引用,所以在它的活动记录中也不需要静态链接。有些人要求C++应该增加嵌套函数这个特性。 

    千万不要把活动记录中的静态链接同前面章节里提到的静态链接混为一谈。前者允许上层引用词法上外层过程的局部数据,而后者表示一种把所有库的副本放于可执行文件中的过时方法。在前面的章节里,“静态”表示“在编译时进行”;在本章,它表示程序的词法布局。

    #include

    void a(int i) {
        if (i > 0) {
            printf("i has reached %d.\n", i);
            a(--i);
        } else {
            printf("i has reached zero.\n");
        }
        return;
    }

    int main() {
        a(2);
    }

    /* 输出:

    */ 
    每一个虚线框显示一段进行函数调用的源文件。已执行的语句用粗体表示。从控制从一个函数
    转到另一个函数时,堆栈的新状态现在在下面。程序从main开始执行,堆栈向下生长。

    编译器设计者通过不存储未使用的信息来提高速度。其他的优化措施包括把信息保存于
    寄存器中而不是堆栈中,对简单的函数调用(自身不调用其他函数)不将整个过程活动记录
    录入栈,以及让被调用函数而不是调用者负责寄存器值的保存工作。如果“指向前一个过程
    活动记录的指针”位于过程活动记录内部,就可以简化当前函数返回时返回到前一个过程活动
    记录的任务。


                            图6-5 每个函数调用在运行时创建过程活动记录                     

  • 相关阅读:
    造轮子之文件管理
    Linux搭建C++开发环境
    一.基础算法
    VLAN实验
    java8 新特性5 方法引用
    面试官:做过性能优化?我:任务切片!
    Stack Overflow 临时禁用 ChatGPT 生成内容,网友:人类和AI快打起来!
    2.Java怎么正确停止线程呢?
    【Harmony OS】【ARK UI】ets使用startAbility或startAbilityForResult方式调起Ability
    linux 搭建mycat
  • 原文地址:https://blog.csdn.net/weixin_40186813/article/details/126076771