堆栈基础

一、堆栈基础——内存区域

代码是以进程的形式来执行的,一个进程可能被分配到不同的内存区域去执行:

  • 代码区:这个区域内存储着被装入执行的二进制机器代码,处理器会到这个区域取指并执行
  • 数据区:用于存储全局变量/静态变量等
  • 堆区:进程可以在堆区动态的请求一定大小的内存,并在使用完之后还给堆区。动态分配和回收是堆区的特点,是向高地址扩展的内存区域,通常由程序员来管理
  • 栈区:用于动态的存储函数之间的调用关系,以保证调用函数在返回时恢复到母函数中继续执行,是由操作系统来管理的。


    image.png

栈区

栈是向低地址扩展的数据结构,入栈时是从高地址向低地址扩展,是一块连续的内存的区域。通常用来存储局部变量。栈顶的地址和栈的最大容量是系统预先规定好的,在windows下,栈的默认大小是2M,如果申请的空间超过栈的剩余空间,将提示overflow


image.png

堆区

堆是向高地址扩展的数据结构,是不连续的内存区域,堆的大小受限于计算机的虚拟内存。
操作系统中有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表

  • 寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序
  • 由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动将多余的那部分重新放入空闲链表中。
  • 对于大多数系统,会在这块内存空间中的首地址记录本次分配的大小,这样代码中的delete语句才能正确的释放本内存空间


    image.png

区别

申请方式

栈:由系统自动分配。
堆:需要程序员自己申请,并指明大小,在c中malloc函数 例如p1=(char *)malloc(10)

申请效率

栈:系统自动分配,速度比较快,但是程序员无法控制
堆:由程序员分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来方便


二、堆栈基础——函数调用

函数调用时,将借助系统栈来完成函数状态的保存和恢复


image.png

主函数中调用函数A,函数A又调用的函数B,函数B的返回值加上一个值作为函数A的返回值,最后函数A的返回结果作为主函数的返回值


image.png
  • 这些代码区中精确的跳转都是在与系统栈巧妙的配合过程中完成的。
  • 当函数被调用时,系统栈会为这个函数开辟一个新的栈帧,并把它压入栈中。每个栈帧对应着一个未运行完的函数。栈帧中保存了该函数的返回地址和局部变量。从逻辑上讲,栈帧就是一个函数执行的环境:函数参数、函数的局部变量、函数执行完后返回到哪里等待。
  • 当函数返回时,系统栈会自动弹出该函数所对应的的栈帧,弹出栈帧意味着这个函数执行完毕。


    image.png

    image.png

函数调用的步骤

栈是先进后出的数据结构

  • (1)参数入栈——将参数从右向左依次压入系统栈中
  • (2)返回地址入栈——将当前代码区调用指令的下一条指令地址压入栈中,供函数返回时继续执行
  • (3)代码区跳转——处理器从当前代码区跳转到被调用函数的入口(就是跳转到被调用的函数处,再取指令时就从被调用的函数的代码区开始取指令)
  • (4)栈帧调整。取指令时,会包括栈帧调整。具体包括
    保存当前栈帧状态值,已备后面恢复本栈帧时使用。
    将当前栈帧切换到新栈帧。

三、堆栈基础——常见寄存器和栈帧

寄存器

寄存器是中央处理器CPU的组成部分。寄存器是有限存储容量的高速存储部件,它们可以用来暂存指令、数据和地址。我们常常看到32位CPU、64位CPU这样的名称,其实指的就是寄存器的大小。32位CPU寄存器大小就是4字节。CPU越大说明CPU一次处理的数据就越多
为了缓解CPU和内存效率不对等的问题,CPU自带一级缓存和二级缓存,但是这些缓存还是不够快,于是将一些最常访问的数据存放在寄存器中(寄存器的读写速度比内存快很多),CPU优先读取寄存器,再由寄存器跟内存交换数据。

image.png

CPU、寄存器和内存
CPU运算所需数据只能从寄存器存取,寄存器会先从高速缓存区读取数据,不命中才会从内存读数据。而内存中的数据也是先从磁盘缓存区(disk cache)读数据,或者在磁盘缓冲区(disk buffer)存数据,最后才会交际最慢的磁盘。

ESP和EBP两个寄存器

image.png
栈指针寄存器ESP(extended 寄存器 stack栈 pointer指针)

ESP标识了当前栈帧的顶部(相当于top)

基址指针寄存器ESP(extended 寄存器 base基址 pointer指针)

ESP标识了当前栈的底部(相当于base)

ESP和EBP之间的内存空间为当前帧,当前帧指的是系统栈中最顶部的栈帧。**


image.png

函数栈帧中包含的信息

  • 局部变量
  • 栈帧状态值,用于在本帧被弹出后恢复出上一个栈帧
  • 函数返回地址,以便函数返回时能够恢复到函数被调用前的代码区中继续执行指令


    image.png

指针寄存器EIP(extended 寄存器 instruction pointer指针)

指针寄存器,期内存放着一个指针,该指针永远指向下一条等待执行的指令地址。
函数调用完毕后,返回原来函数指令运行的一个关键操作是,将栈帧中保持的返回地址装入EIP寄存器。
控制了EIP寄存器就相当于控制了进程,我们让EIP指向哪里,CPU就会去执行哪里的指令。


image.png

image.png

之所以将ESP值装入EBP是因为新的栈帧是位于旧的栈帧上面,所让旧的栈帧的顶部ESP成为新的栈帧的底部EBP

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351