zoukankan      html  css  js  c++  java
  • 堆栈帧的组织——C/C++内存管理必须掌握

    程序栈

          说到堆栈帧,你得先说说程序栈。

          记忆功能程序堆栈区是支持操作,通常共享堆。

    程序栈通常占领内存区域的下部,而堆用的是上部。

          程序栈存放栈帧,栈帧有时候也称为活跃记录或活跃帧。栈帧存放函数參数和局部变量。堆存放动态内存。

          调用函数时,函数的栈帧被推到栈上。栈向上长出一个栈帧。

    当函数终止时,其栈帧从程序栈上弹出。

    栈帧所使用的内存不会被清理,可是终于可能会被推到程序栈上的还有一个栈帧覆盖。

           动态分配的内存来自堆。堆向下生长。随着内存的分配与释放。堆中会布满碎片。

    虽然堆是向下生长的,可是这仅仅是大体方向,实际内存可能位于堆上的任何位置。

     

    栈帧的组织

        

     栈帧由以下几个元素组成:

        返回地址:函数完毕后要返回的程序内部地址
       局部数据存储:为局部变量分配的内存
       參数存储:为函数參数分配的内存
       栈指针和基指针:执行时系统用来管理栈的指针    

         栈指针通常指向栈顶部。基指针通常存在并指向栈帧内部的地址,比方返回地址,用来协调訪问栈帧内部的元素。

    这两个指针都不是C指针,他们是执行时系统管理程序栈的地址。

        以下这个函数给出实例:

    float average(int *arr, int size){
         int sum;
         printf("arr: %p
    ",&arr);
         printf("size: %p
    ",&size);
         priintf("sum: %p
    ",&sum);
    
         for(int i = 0;i < size;i ++){
              sum +=arr[i];
         }
        
          return (sum *1.0f) / size;
    }
    
    //output
    //arr: 0x500
    //size: 0x504
    //sum: 0x480


      当中參数地址和局部变量之间的空档。保存的是执行时系统管理栈所需的其它栈帧元素。

      系统在创建栈帧时,将參数以跟声明时相反的顺序推到栈上,最后推入局部变量。在这个样例中,size在arr之后被推入。通常,接下来会推入函数调用的返回地址。然后是局部变量。推入它们的顺序和在代码中的顺序相反!

       从原理上说,本例中的栈向上生长。只是栈帧的參数和局部变量以及新栈帧被加入到了低内存地址。

    栈的实际生长方向和实际相关。

       for语句中的i没有包括在栈帧中。这是由于C语言中把块语句当成“微型”函数。

       将栈帧推到程序栈上时,系统可能会耗尽内存,这样的情况叫做栈溢出,一般会导致程序非正常终止。要牢记住每个线程都有自己的程序栈,一个或多个线程访问存储器中的同一个对象可能会造成冲突。

    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    Java之lambda表达式
    修改IntelliJ IDEA的java编译版本
    no route to host解决方案、Failed to start LSB: Bring up/down networking的问题解决方案
    spark转换集合为RDD
    spark编写word count
    nexus
    spark 源码安装
    spark shell
    maven
    git
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4631392.html
Copyright © 2011-2022 走看看