一、C/C++的内存分区
- C/C++把内存分为:栈区、堆区、全局区(静态区)、常亮区、代码区
- 那“内存四区”和“内存五区”有什么区别吗?
- 其实“内存四区”和“内存五区”指的东西都是完全一样的
- 内存五区为:栈区、堆区、全局区(静态区)、常亮区、代码区
- 内存四区为:栈区、堆区、数据区(全局区(静态区)、常亮区)、代码区
- 因此从上面可以看出,对于内存四区而言,其只是把全局区(静态区)和常亮区合并为一个数据区而已,其实内容都是完全一样的
二、内存五区
栈区
- 栈区主要存放局部变量、函数调用参数等
- 栈区由编译器自动分配和释放
- 栈属于 计算机系统的数据结构,进栈出栈有相应的计算机指令支持,而且分配专门的寄存器 存储栈的地址,效率分高,内存空间是连续的,但栈的内存空间有限
堆区
- 使用malloc()/new()申请的内容存储在堆区
- 堆区由程序员手动分配,因此需要自己释放,如果不释放就会产生内存的泄漏
- 内存空 间几乎没有限制,内存空间不连续,因此会产生内存碎片。操作系统有一个记录空间 内存的链表,当收到内存申请时遍历链表,找到第一个空间大于申请空间的堆节点, 将该节点分配给程序,并将该节点从链表中删除。一般,系统会在该内存空间的首地 址处记录本次分配的内存大小,用于 delete 释放该内存空间
全局区(静态区)
- 全局区分为两个段:
- DATA段:存储初始化的全局变量、初始化的静态变量
- BSS段:存储未初始化的全局变量、未初始化的静态变量
- 其中BSS段会在程序执行前,将内容全部置为0,所以未初始化的全局变量和未初始化的静态变量的值都为0
常量区
代码区
三、内存四区
- 文章最前面已经说过了,内存四区与内存五区的内容是完全一样的,只是其把“全局区(静态区)”和“常量区”合并为一个“数据区”而已
- 因此,内存四区为:
- 栈区
- 堆区
- 数据区(包含全局区(静态区)和常量区)
- 代码区
四、代码演示
int a = 0; //全局初始化区
char *p1; //全局未初始化区
int main(){
int b; //栈
char s[] = "abc"; //栈
char *p2; //栈
char *p3 = "123456"; //123456\0在常量区,p3在栈上
static int c = 0; //全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20); //分配得来得10和20字节的区域就在堆区
strcpy(p1, "123456"); //123456\0放在常量区, 编译器可能会将它与p3所指向的"123456"优化成一块
return 0;
}
五、栈和堆的区别
- 存储的内容:
- 栈存局部变量、函数参数等
- 堆存储使用 new、malloc 申请 的变量等
- 申请的方式:
- 申请后系统的响应:
- 栈——只要栈的剩余空间大于所申请空间,系统将为程序提供 内存,否则将报异常提示栈溢出
- 堆——首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申 请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空 闲结点链表 中删除,并将该结点的空间分配给程序
- 申请大小的限制:
- Windows 下栈的大小一般是 2M,堆的容量较大
- 申请效率的对比:
- 栈由系统自动分配,速度较快
- 堆使用 new、malloc 等分配,较慢