如果大家学习过C语言那么一定知道内存管理,简单来说内存管理就是向堆申请空间的过程,C语言有malloc,calloc,realloc等函数来申请空间,free来释放申请的空间,C++也又属于自己的内存管理,比如用new来申请空间,用delete来释放空间等,下面就跟着我来一起学习吧!
一、C/C++内存分布
C/C++中程序内存区域划分:
- 内核空间:用户代码不能读写。
- 栈:又叫堆栈,存放非静态局部变量/函数参数/返回值等等,栈是向下增长的。
-
内存映射段:是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口
创建共享共享内存,做进程间通信。
-
堆:用于程序运行时动态内存分配,堆是可以上增长的。
-
数据段:存储全局数据和静态数据。
-
代码段:存储可执行的代码/只读常量
在学习具体内容之前,我们先看一段代码:
int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
static int staticVar = 1;
int localVar = 1;
int num1[10] = { 1, 2, 3, 4 };
char char2[] = "abcd";
const char* pChar3 = "abcd";
int* ptr1 = (int*)malloc(sizeof(int) * 4);
int* ptr2 = (int*)calloc(4, sizeof(int));
int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
free(ptr1);
free(ptr3);
}
现在开始提问:
现有A、B、C、D四个选项,分别是栈、堆、数据段(静态区)、代码段(常量区)。
globalVar在哪里?____
staticGlobalVar在哪里?____
staticVar在哪里?____
localVar在哪里?____
num1 在哪里?____
char2在哪里?____
*char2在哪里?___
pChar3在哪里?____
*pChar3在哪里?____
ptr1在哪里?____
*ptr1在哪里?____
大家先思考3分钟。
现在公布答案:
globalVar在哪里?__C__
staticGlobalVar在哪里?_C___
staticVar在哪里?__C__
localVar在哪里?_A___
num1 在哪里?__A__
char2在哪里?__A__
*char2在哪里?_A__
pChar3在哪里?__A__
*pChar3在哪里?_D___
ptr1在哪里?_A___
*ptr1在哪里?__B__
大家做对了吗?
用一张图就可以搞清楚上面的关系。
我们学习内存管理主要是针对堆上来开辟和释放空间。
二、C语言中动态内存管理方式
在C语言中主要用malloc/calloc/realloc/free这4个函数来动态管理内存。
void Test()
{
int* p1 = (int*)malloc(20);
if(p1 == NULL)
{
perror("malloc fail");
return;
}
int* p2 = (int*)calloc(4, sizeof(int));
if(p2 == NULL)
{
perror("calloc fail");
return;
}
int* p3 = (int*)realloc(p2, sizeof(int) * 10);
{
if(p3 == NULL)
{
perror("realloc fail");
return;
}
}
free(p1);
free(p3);
}
malloc、calloc、realloc它们三个都是在堆中开辟空间,但有所不同。
malloc和calloc都是直接开辟空间,但用malloc开辟的空间不会初始化,而用calloc开辟的空间所有字节会初始化为0。
而realloc是用来扩容,在已开好的空间的基础上扩容,若后面空间足够就直接扩容(p3==p2),若后面空间不够就重新找一个足够的空间扩容(之前的p2指向的空间自动释放了)。所以直接free(p3)就可以了,不用free(p2)。
当然,当开辟的空间较大时,可能会发生开辟失败,返回NULL指针。对于realloc空间开辟失败返回NULL,但它扩容之前的那块空间不会被释放。
如果不释放内存,就会造成内存泄漏,影响程序正常运行。
三、C++内存管理方式
C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦(稍后会讲