动态内存管理函数
1. malloc函数
void* malloc(size_t size);
功能:向堆区的空间中申请一块大小为size个字节的空间,返回指向这块空间的指针
- 如果开辟失败会返回一个NULL指针,因此要检查malloc的返回值,避免返回NULL指针后再访问空指针
- malloc申请的空间,程序退出后会还给操作系统
- 可以用free函数释放空间,释放空间后的指针需置NULL,避免成为野指针
2. free函数
void free(void* ptr);
功能:释放动态内存空间
- free不能释放不是动态开辟的空间
- 若参数ptr为NULL指针,则free什么都不做
- malloc和free都声明再头文件stdlib.h头文件中
3. calloc函数
void* calloc(size_t num, size_t size);
功能:为num个大小为size的元素开辟空间,并且把空间中每个字节初始化为0
- 与malloc的区别在于会初始化为0
- int* p = (int*)calloc(10, sizeof(int));
4. realloc函数
void* realloc(void* ptr, size_t size);
功能:为ptr指向的空间扩充为或缩小成size个字节的大小,返回扩充或缩小后的地址
- realloc的出现让动态内存管理更灵活
- 当扩充内存时会出现两种情况:
- 情况一:原有空间之后有足够大的空间,那么直接扩充,返回原来的地址
- 情况二:原有空间之后没有足够的空间
- 此时realloc会重新找一块内存
- 然后将原来内存里的值靠白在新的空间中
- 再释放原来的空间
- 返回当前的新地址
注意:开辟的空间也可能失败,所以开辟完空间要判断是否为空
特别地:realloc开辟完空间要用新的指针接收,否则,如果开辟失败返回NULL指针,那么原有的地址就丢失了,也无法释放
int* p = (int*)malloc(40);
int* newp = (int*)realloc(p, 80);
if(newp != NULL)
{
//如果不为空说明开辟成功,后续用到的其实是指针p,newp只是临时指向新开辟的空间,既然开辟成功,那就让p指向新地址,置空newp
p = newp;
newp = NULL;
}
else
{
perror("realloc");//这是一个打印错误提示信息的函数
}
常见错误
1. 对NULL指针解引用
int* p = (int*)malloc(40);
*p = 20;
若malloc开辟失败返回NULL,则*p访问的就是空指针
2.对动态开辟空间的越界访问
int* p = (int*)malloc(40);
if(p == NULL)
{
perror("malloc");
return 1;
}
实际上当i>=10时,就超出了访问权限,因为空间只开辟了40个字节
for(int i = 0; i < 20; i++)
{
p[i] = i;
}
free(p);
p = NULL;
3. 对非动态开辟内存使用free释放
int a = 20;
int* p = &a;
free(p);
4.使用free释放一块动态内存的一部分
int *p = (*int)malloc(40);
p = p+2;
free(p);