栈帧的组织——C/C++内存管理必须掌握的

程序栈

说到栈帧,不得不先说说程序栈。

程序栈是支持函数执行的内存区域,通常和堆共享。程序栈通常占据内存区域的下部,而堆用的是上部。

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

调用函数时,函数的栈帧被推到栈上,栈向上长出一个栈帧。当函数终止时,其栈帧从程序栈上弹出。栈帧所使用的内存不会被清理,但是最终可能会被推到程序栈上的另一个栈帧覆盖。

动态分配的内存来自堆,堆向下生长。随着内存的分配与释放,堆中会布满碎片。尽管堆是向下生长的,但是这只是大体方向,实际内存可能位于堆上的任意位置。

栈帧的组织

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

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

栈指针通常指向栈顶部。基指针通常存在并指向栈帧内部的地址,比如返回地址,用来协调访问栈帧内部的元素。这两个指针都不是C指针,他们是运行时系统管理程序栈的地址。

下面这个函数给出实例:

float average(int *arr, int size){
     int sum;
     printf("arr: %p\n",&arr);
     printf("size: %p\n",&size);
     priintf("sum: %p\n",&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语言中把块语句当成“微型”函数。

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

栈帧的组织——C/C++内存管理必须掌握的

时间: 2024-07-31 10:29:10

栈帧的组织——C/C++内存管理必须掌握的的相关文章

堆栈帧的组织——C/C++内存管理必须掌握

程序栈 说到堆栈帧,你得先说说程序栈. 记忆功能程序堆栈区是支持操作,通常共享堆. 程序栈通常占领内存区域的下部,而堆用的是上部. 程序栈存放栈帧,栈帧有时候也称为活跃记录或活跃帧.栈帧存放函数參数和局部变量.堆存放动态内存. 调用函数时,函数的栈帧被推到栈上.栈向上长出一个栈帧. 当函数终止时,其栈帧从程序栈上弹出. 栈帧所使用的内存不会被清理,可是终于可能会被推到程序栈上的还有一个栈帧覆盖. 动态分配的内存来自堆.堆向下生长.随着内存的分配与释放.堆中会布满碎片. 虽然堆是向下生长的,可是这

浅谈C++容器动态内存管理的优化

在信息学竞赛中,C++的容器的用途非常广泛,但经常因常数过大而超时.怎样才能提高它们的效率呢? 我们知道,容器是存储同一类对象的对象,既然"对象"我们无法改变,那么我们只能从"存储"入手,不难想到,不同容器在实现上的根本区别是它们对应着不同的内存组织方式,内存管理无疑是这种实现的核心,所以优化内存管理是加快容器效率的最好途径之一. 一.内存分配器简介 怎样才能优化内存管理呢?很简单,C++为我们提供了这样的接口,我们可以通过自定义容器模板中的最后一个allocato

&lt;&lt;深入分析javaWeb技术内幕&gt;&gt;读书笔记-JVM内存管理2

JVM垃圾回收策略 1.静态内存分配和回收 编译时已经确定了内存空间大小,程序被加载后则一次性分配好内存空间.程序结束后,则对应栈帧撤销,分配的静态内存空间则被回收. 2.动态内存分配和回收 程序运行动态分配内存空间,回收时则由垃圾收集器负责. 3.垃圾收集器 A.正确的检测出垃圾对象(关键功能) B.释放垃圾对象占用的内存空间 4.基于分代的垃圾收集算法(hostpot) 算法设计思路: 把对象按照寿命的长短进行分组(年轻代,年老代),新创建的对象分配在年轻代中,对象经过几次垃圾回收后,仍然存

关于内存管理

最近都是ARC写代码,弄了一下午整理了一下MRC的使用,原创哦!~!~~ 1 任何继承NSObject的对象,都需要管理内存2 基本数据类型放到栈中,对象放到堆空间中3 oc对象 nil指针 release 不报错4 僵尸对象检测 stop右->Edit Scheme->Diagncatics-> Objective-C->勾选Enable zomble objects ---------单个对象的内存管理--------- 每个对象给引用计数器分配四个字节的存储空间,当对象的引用

C 内存管理那些事儿

一.内存介绍 本文主要介绍C内存管理基本概念,以及C语言编译后的可执行程序的存储结构和运行结构. 在用户存储空间,一个C程序的在内存中的分配分类5大部分:代码段.全局已初始化数据段.bss段.堆和栈.其中各部分具体所指: 1.代码段(text segment)    存放CPU执行的机器指令(machine instructions).代码区通常是只读的,使其只读的原因是防止程序意外地修改了它的指令. 2.全局已初始化数据段    存入的是初始化的全局变量.静态变量(包括全局静态变量和局部静态变

Linux内存管理 (一) 内存组织

内存管理是内核最复杂同时也是最重要的一部.其特点在于非常需要处理器和内核之间的协作. 首先内存划分为结点,在内核中表示为pg_data_t,每个结点划分为内存域. 以下的所有数据结构或代码都做了不同程度的精减,一方面是为了保留相关代码,除去细枝末叶,另一方面是为了美观. 结点的数据结构为 <mmzone.h>typedef struct pglist_data { struct zone node_zones[MAX_NR_ZONES]; /*内存结点所包含的内存域数组*/ struct zo

转:内存区划分、内存分配、常量存储区、堆、栈、自由存储区、全局区[C++][内存管理][转载]

内存区划分.内存分配.常量存储区.堆.栈.自由存储区.全局区[C++][内存管理][转载] 一. 在c中分为这几个存储区1.栈 - 由编译器自动分配释放2.堆 - 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收3.全局区(静态区),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域.- 程序结束释放4.另外还有一个专门放常量的地方.- 程序结束释放                          

linux内核探索之内存管理(二):linux系统中的内存组织--结点、内存域和页帧

本文主要参考<深入linux内核架构>(3.2节)及Linux3.18.3内核源码 概述:本文主要描述了内存管理相关的数据结构:结点pg_data_t.内存域struct zone以及页帧(物理页):struct page ,以及该结构相关的一些基本概念. 1. 概述 内存划分为接点,每个结点关联到系统中的一个处理器,在内核中表示为pg_data_t. 各个结点又划分为内存域,比如DMA内存域,高端内存域,普通内存域. 内核内存域的宏: enum zone_type { #ifdef CONF

JAVA内存管理之堆内存和栈内存

我们常常做的是将Java内存区域简单的划分为两种:堆内存和栈内存.这种划分比较粗粒度,这种划分是着眼于我们最关注的.与对象内存分配密切相关的两类内存域.其中栈内存指的是虚拟机栈,堆内存指的是java堆. 1.栈内存,即虚拟机栈.每个方法被执行的时候都会同时创建一个栈帧,用来存储局部变量,操作栈,动态链接,方法出口等信息.局部变量包括各种基本类型的变量和对象的引用变量都是在方法的栈内存中分配.其中,64位长度的long和double类型的数据占用2个局部变量的空间,其他数据类型只占用1个.局部变量