zoukankan      html  css  js  c++  java
  • 程序的内存空间 堆空间和栈空间的区别

     一个由C/C++编译的程序占用的内存分为以下几个部分:

    1、栈区(stack):

    由编译器自动分配释放,其操作方式类似于数据结构的栈。

    用于存放函数的参数值,用户程序临时创建的局部变量等,即函数括号"{}"中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此之外,在函数被调用时,其参数也会被压入发起调用的进程栈中,等到调用结束后,函数的返回值也会被存放回栈中。

    由于栈的后进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,可以把栈看成一个寄存、交换临时数据的内存区。

    2、堆区(heap):

    一般是由程序员分配释放,若程序员不释放的话,程序结束时可能由OS回收。它与数据结构的堆是两回事,分配方式倒是类似于数据结构的链表。

    用于存放程序运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。

    当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。

    3、全局区(static):也叫静态数据内存空间,存储全局变量和静态变量,全局变量和静态变量的存储是放一块的,初始化的全局变量和静态变量放一块区域,没有初始化的在相邻的另一块区域,程序结束后由系统释放。

    (1)BSS段(Block Started by Symbol):通常指用来存放程序中未初始化的全局变量的一块内存区域。属于静态内存分配。

    (2)数据段:通常指用来存放程序中已初始化的全局变量的一块内存区域。属于静态内存分配。

    4、文字常量区:常量字符串就是放在这里,程序结束后由系统释放。

    5、程序代码区:

    通常指用来存放程序执行代码(函数体的二进制代码)的一块内存区域。

    这部分区域的大小在程序运行前就已经确定,并且该内存区域通常属于只读,某些架构也允许代码段为可写,即允许修改程序。

    在代码段中,也有可能包含一些只读的常数变量,如字符串常量等。

    假如机器中有数个进程运行相同的一个程序,那么它们就可以使用同一个代码段。

    堆和栈的区别:
    一、由以上综述就可以得知,他们程序的内存分配方式不同。

    二、申请和响应不同:
    1、申请方式:stack由系统自动分配,heap需要程序员自己申请,C中用函数malloc分配空间,用free释放,C++用new分配,用delete释放。
    2、申请后系统的响应:
    栈:只要栈的剩余空间大于所申请的空间,体统将为程序提供内存,否则将报异常提示栈溢出。
    堆:首先应该知道操作系统有一个记录内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请的空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样代码中的delete或free语句就能够正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会将多余的那部分重新放入空闲链表中。

    三、 申请的大小限制不同:
    栈:在windows下,栈是向低地址扩展的数据结构,是一块连续的内存区域,栈顶的地址和栈的最大容量是系统预先规定好的,能从栈获得的空间较小。
    堆:堆是向高地址扩展的数据结构,是不连续的内存区域,这是由于系统是由链表在存储空闲内存地址,自然堆就是不连续的内存区域,且链表的遍历也是从低地址向高地址遍历的,堆得大小受限于计算机系统的有效虚拟内存空间,由此空间,堆获得的空间比较灵活,也比较大。

    四、申请的效率不同:
    栈:栈由系统自动分配,速度快,但是程序员无法控制。栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。
    堆:堆是由程序员自己分配,速度较慢,容易产生碎片,不过用起来方便。堆则是C/C++函数库提供的,它的机制是很复杂的。

    五、堆和栈的存储内容不同:
    栈:在函数调用时,第一个进栈的是主函数中函数调用后的下一条指令的地址,然后是函数的各个参数,在大多数的C编译器中,参数是从右往左入栈的,当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令。
    堆:一般是在堆头部用一个字节存放堆的大小,具体内容由程序员安排。

    六、碎片问题:

    对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。

    对于栈来讲,则不会存在这个问题,因为栈是先进后出得队列,它们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出。

    七、分配方式:

    堆都是动态分配的,没有静态分配的堆。

    栈有两种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloc函数进行分配,但是栈的动态分配和堆是不同的,它的动态分配是由编译器进行释放,无需我们手工实现。

  • 相关阅读:
    el-select下拉框选项太多导致卡顿,使用下拉框分页来解决
    vue+elementui前端添加数字千位分割
    Failed to check/redeclare auto-delete queue(s)
    周末啦,做几道面试题放松放松吧!
    idea快捷键
    解决flink运行过程中报错Could not allocate enough slots within timeout of 300000 ms to run the job. Please make sure that the cluster has enough resources.
    用.net平台实现websocket server
    MQTT实战3
    Oracle 查看当前用户下库里所有的表、存储过程、触发器、视图
    idea从svn拉取项目不识别svn
  • 原文地址:https://www.cnblogs.com/argenbarbie/p/5400373.html
Copyright © 2011-2022 走看看