一、内存分几个区原因
系统运行时不能所有数据都读取到CPU寄存器,所以需要有缓存,缓存不够用了所以有多级缓存。缓存的存储器毕竟还是相对昂贵的,所以还有内存(也叫外存)。但是数据在内存中的是怎样存放,这又是一个问题。
- 首先从字节层面看:信息在计算机肯定是0/1的bit比特位形式存储,习惯是8bit作为一个字节作为一个有意义的存储单位,但是有些数据的最小存储单位是多个字节,例如:int类型。多字节的数据在内存或者寄存器存储方式可以分为:大端、小端。
- 整体内存层面看:内存中有执行的二进制代码程序、有代码运行时需要不断改变的变量、有代码运行调用但是不需要改变的常量、还有需要的数据等等。内存中的数据可以看做多小电容,不停读写修改会让这些电容充放电,充放电频繁会产生磁场对附近的其他数据影响。为了抵消这些影响,系统把内存分为多个区,这样可以有效提升数据的安全性。企业级服务器使用的一般都是带ECC(Error Correcting Code)错误检查纠正技术的内存。
二、主流说法
程序在内存中主要分几个区域,每个区域存储那些数据(此处把程序、变量等都看做数据),主要有以下几种说法:
- 第一种说法是:5个区域(堆区、栈区、全局/静态存储区、常量存储区、自由存储区)。
- 第二种说法是:5个区域(堆区、栈区、全局/静态区、(字符)常量存储区、程序代码区)。
- 第三种说法是:5个区域(bss是英文Block Started by Symbol的简称、text段是程序代码段、data包含静态初始化的数据、stack保存函数的局部变量和参数、heap保存函数内部动态分配内存)
- 第四种说法是:4个区域(堆区、栈区、全局/静态存储区、常量区)。
2.1相同部分对比
堆区 | 栈区 | 全局/静态存储区 |
|
|
|
注意:堆区数据有先进先出特性,栈区数据有后进先出特性,但是并不是说只能依次取数据。具体怎么取堆/栈区中间数据需要看堆/栈是怎么实现的。如果栈是用常见的最大/最小树结构实现,那么就是取中间数据后再对其进行排序即可。
2.2自由存储区、堆区
主要讨论点是:自由存储区(free store),堆区有什么区别
- 很多博客划分自由存储区与堆的分界线就是new/delete与malloc/free。
- 然而,尽管C++标准没有要求,但很多编译器的new/delete都是以malloc/free为基础来实现的。那么借以malloc实现的new,所申请的内存是在堆上还是在自由存储区上?
- 从技术上来说,堆(heap)是C语言和操作系统的术语。堆是操作系统所维护的一块特殊内存,它提供了动态分配的功能,当运行程序调用malloc()时就会从中分配,稍后调用free可把内存交还。
自由存储是C++中通过new和delete动态分配和释放对象的抽象概念,通过new来申请的内存区域可称为自由存储区。 - 基本上,所有的C++编译器默认使用堆来实现自由存储,也即是缺省的全局运算符new和delete也许会按照malloc和free的方式来被实现,这时由new运算符分配的对象,说它在堆上也对,说它在自由存储区上也正确。但程序员也可以通过重载操作符,改用其他内存来实现自由存储,例如全局变量做的对象池,这时自由存储区就区别于堆了。我们所需要记住的就是:
堆是操作系统维护的一块内存,而自由存储是C++中通过new与delete动态分配和释放对象的抽象概念。堆与自由存储区并不等价。
2.3堆区和栈区区别
堆区和栈区主要区别集中在以下几点:
- 管理方式不同。
- 空间大小不同。
- 能否产生碎片不同。
- 生长方向不同。
- 分配方式不同。
- 分配效率不同。
具体区别参考下表:
堆区 | 栈区 |
|
|
- 堆和栈相比,由于大量new/delete的使用,容易造成大量的内存碎片。
- 由于没有专门的系统支持,效率很低。
- 由于可能引发用户态和核心态的切换,内存的申请,代价变得更加昂贵。
- 所以栈在程序中是应用最广泛的,就算是函数的调用也利用栈去完成,函数调用过程中的参数,返回地址,EBP和局部变量都采用栈的方式存放。
- 所以,使用的时候尽量用栈,而不是用堆。
- 虽然栈有如此众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,还是用堆好一些。
- 无论是堆还是栈,都要防止越界现象的发生(除非你是故意使其越界),因为越界的结果要么是程序崩溃,要么是摧毁程序的堆、栈结构,产生以想不到的 结果,就算是在程序运行过程中,没有发生上面的问题,还是要小心,说不定什么时候就崩掉。
三、个人感受
对内存分区有一些了解,知道为什么内存中数据要分开存,然后了解大概可以分几个区即可。具体分几个,new的对象存储在哪里,malloc申请的内存在哪里这些细节需要看具体的编译器和操作系统。如果不是做编译器的,可以对这些有了解即可。
四、相关参考
非常感谢以下的博客文章: