本文主要说明C++的内存管理。
对于C++的内存结构,主要有两种说法,一个是{栈区,堆区,全局区(静态区), 常量区,代码区}。另一种说法为{栈区,堆区,全局区(静态区), 自由存储区}。
在第二种说法中,增加了自由存储区,其与堆区没有本质区别,只是new
分配的存储在堆区,malloc
分配的存储在自由存储区。所以我们重点看第一种说法。
I、栈区
1、在函数中,函数的局部变量的存储单元在栈上,函数执行结束后栈区自动释放。
2、栈内存分配效率高,由操作系统和编译器自动分配,但存储空间有限。
II、堆区
1、堆区中的内存由程序员自己创建并维护,每个new
都应该对应于一个delete
,如果程序员忘记释放堆内存,则在程序最后结束后会由操作系统完成释放,但在程序运行过程中可能会造成堆区越来越大,从而造成内存溢出。
2、 明确区分栈与堆
理解这个问题最好的办法就是下面的例子:
void f() {
int *p = new int[5];
}
在上面的例子中,p存储在栈区,因为其是函数的局部变量,而p指向的空间(是一个存储int的数组)则存储在堆区。
III、全局区(静态区)
1、这部分内存区存储程序的全局变量和静态变量,其中关于静态变量的详细内容可以参见:C++ 小探static关键字
IV、常量区
1、常量区内存空间存储常量(包括字符串,等内容),如下面示例:
char *p = "123456";
其中指针p存储在栈区,而123456存储在常量区。
V、代码区
1、代码区存放函数体的二进制代码。
VI、栈vs堆
1、管理方式不同;
2、空间大小不同:栈的大小一般是以MB为单位的。
3、能否产生碎片不同:由于管理方式的不同,所以堆更容易产生碎片。这是由于频繁的调用new/delete而造成内存空间不连续。而对于栈,其由操作系统管理,每次弹出的内存块意味着它上面的内存块也已经弹出,所以几乎不会产生碎片。
4、生长方式不同:堆的生长方向是向上的,也就是向着内存地址增加的方向;而对于栈,其的生长放下是向下的,向着内存地址减小的方向生长。
5、分配方式不同:堆是动态分配的;而栈其实具有两种分配方式,在栈的静态分配中是由编译器完成的,如局部变量的分配;动态分配的栈是由函数 alloca
完成的,虽然是动态分配的栈,但是我们也无需对其进行手工释放,也是由操作系统完成的。
6、分配效率不同: 栈是及其系统提供的数据结构,计算机对其底层提供支持,有专门的寄存器存放栈的地址,并有专门的指令执行push/pop等操作。而堆是由库函数提供的,其机制很复杂。
【参考】
[1] C/C++内存管理详解
网友评论