文章目录
前言
本篇文章旨在简单介绍动态内存管理的四个主要的函数,其次我们会通过一些代码演示一些使用时的常见错误,帮助读者加深动态内存管理的这四个函数。
一、malloc是什么?
众所周知,在C语言的学习中,我们经常要用到动态内存管理。即我们会根据自身程序的需要,向内存申请空间,结束释放它。而malloc正是这样的一个申请内存空间的函数。
调用形式: void* malloc (size_t size);
其中size代表向内存申请空间的大小,而void*表示malloc函数的返回类型。由于malloc不知道开辟空间的具体类型,因此我们需要自定义类型,将所开辟的空间运用到我们要使用的数据类型。
功能: 向内存申请size字节的一块内存空间
开辟成功:返回一个指向开辟好空间的指针
开辟失败: 返回一个NULL指针
分配内存空间的机制: 注意,malloc开辟的内存是在堆上进行的。malloc()从堆里面获得空间,也就是说函数返回的指针是指向堆里面的一块内存。操作系统中有一个记录空闲内存地址的链表。当操作系统收到程序的申请时,就会遍历该链表,然后就寻找第一个空间大于所申请空间的堆结点,然后就将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。【摘自:C语言的malloc和free函数]
使用案例:
int* p = (int*)malloc(40);
//这行代码的意思是:开辟一块40字节的内存空间,
//并且强制转化为整型数组类型,函数的返回值为指向该数组首地址的指针,并把该指针赋值给整型指针变量p。
注意事项
由于malloc操作是在堆上完成的,堆的特点是你申请了空间,你不还我也不要。因此malloc使用完后一定要记得释放这块空间,否则会出现内存泄漏的情况!!而释放内存空间的函数就是free函数~(有借有还,再借不难嘛)
二、free是什么?
上文中我们讲到,free函数就是用来释放内存空间的函数,这里我们隆重介绍free~
函数原型:void free (void* ptr);
其中ptr的意思是释放ptr所指向的一块内存空间。
注意: 1. 如果ptr是空指针,那么free不会做任何事情
2. 请注意,该函数没有改变ptr本身的值,因此它仍然指向相同的位置(现在无效)。
3. 因此free完后,要记得把指针置空,防止非法访问
4. ptr一定要指向之前申请空间的首地址
使用实例:
free(p);
p = NULL;
三、calloc是什么?
calloc的原型:void* calloc (size_t num, size_t size);
calloc同样也是内存分配函数。其中size_t num 表示去分配的元素的数量,size_t size表示每一个元素的大小。void*表示返回的是void类型
注意: 1. calloc最大的特点是其会将每个元素的初始值置为0
2. 如果内存分配失败,则会返回一个NULL指针
应用实例:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)calloc(10, sizeof(int));
int i = 0;
for (i = 0; i < 10; i++)
printf("%d ", *(p + i));
return 0;
}
四、realloc是什么?
函数原型:void* realloc (void* ptr, size_t size);
事实上realloc是改变ptr所指向空间的大小。其中ptr是先前开辟的内存块的指针(也就是指向malloc或calloc申请的内存空间)。size_t size新开辟内存的空间,注意这里是新开辟内存空间,并不是增加了size大小的空间。 其返回值依旧是void*,使用者可以根据自己的需要转化为所需要的类型。
返回值: 其返回值是void*类型,并且指向新开辟空间的地址,这个地址即可能和原来的地址相同,也可能和原来地址不同,这取决于原来地址后面是否能放下新开辟空间。
注意
- 如果ptr是一个空指针,那么realloc的功能和malloc功能相识,同样开辟size大小的内存空间,并返回这块空间的启示地址。
- 如果开辟失败,realloc会返回一个空指针。
- 如果ptr指向的空间之后有足够的空间可以追加,则直接追加,返回的是p原来的起始地址
- 如果ptr指向的空间之后没有足够的空间可以追,那么realloc会找到一块新的内存空间,再把原来内存空间的数据拷贝过来,释放旧的内存空间还给操作系统,最后返回新开辟的内存空间的起始地址。
五、动态内存开辟的常见错误
1. 对NULL指针的解引用操作
int* p = (int*)malloc(INT_MAX);