目录
一、为什么需要动态内存管理
在C语言中,每创建一个变量,就会在内存中根据变量类型开辟出一块空间,这块空间的大小不会根据我们的需求变大变小。只能通过创建变量的方式,在内存中不断地创建新的空间。就像是在编写通讯录的过程中,必须要指定好通讯录的大小,当通讯录中的人数达到最大值的时候,只能通过删除里面的联系人给新人留出空间,这在生活中岂不是很尴尬?为了解决这个问题,C语言中引入了动态内存管理的概念。
二、动态内存管理函数
在介绍动态内存管理函数之前,先给大家介绍一下数据在内存中的存储位置。内存中划分了不同的区域,用来存储不同类型的数据,但是在C语言中我们比较关注三块区域。栈区、堆区和静态区。
栈区:用来保存局部变量、函数的形式参数
堆区:负责动态内存分配、动态内存函数就是像堆区申请的空间
静态区:用来保存全局变量、static修饰的局部变量、常量
-
1、malloc
void* malloc(size_t size)
函数的参数:申请空间的大小,单位是字节,参数类型:size_t
函数的返回值:申请成功返回申请空间的起始位置;申请失败返回NULL,返回值类型:void*
函数功能:通过malloc函数,想堆区申请size个字节的空间
函数的注意事项:malloc返回值类型是void*,需要对其进行强制类型转换;对malloc返回的地址进行判断,防止出现NULL类型
-
2、free
void free(void* p)
函数的参数:地址,参数类型:void*
函数的返回值:返回值为空,返回值类型:void
函数功能:对像堆区申请的动态内存空间进行释放
函数的注意事项:要对已经释放的地址重置成空指针,防止野指针的出现;所有的动态内存开辟的空间都需要进行释放,否则会出现内存泄漏的情况;free函数只能对动态内存函数申请的空间进行释放,不能对其他内存空间使用,如果传递的是NULL则什么也不发生
-
3、calloc
void* calloc(size_t num, size_t size)
函数的参数:参数1,申请空间的个数,参数类型:size_t;参数2,每个空间的大小,参数类型:size_t
函数的返回值:申请成功返回申请空间的起始位置;申请失败返回NULL,返回值类型:void*
函数功能:像堆区申请num个空间,每个空间的大小是size个字节,并对这些空间初始化为0
函数的注意事项:calloc返回值类型是void*,需要对其进行强制类型转换;对calloc返回的地址进行判断,防止出现NULL类型
-
4、realloc
void* realloc(void* p, size_t size)
函数的参数:参数1,需要扩容空间的起始地址,参数类型:void*;参数2,扩容之后的空间大小,参数类型:size_t
函数的返回值:返回值有三种情况。1.扩容成功,当申请扩容的空间后面的空间满足扩容需求,增加空间,返回原空间地址;2.扩容成功当申请扩容的空间后面的空间不满足扩容需求,会在堆区重新找一块满足原空间加上扩容需求的空间,将原空间的内容复制到该空间,返回新空间的地址,并将原空间释放;3.扩容失败,返回NULL,返回值类型:void*
函数功能:扩充空间的最大容量。
函数的注意事项:只能对动态内存开辟的空间进行扩容;realloc返回值类型是void*,需要对其进行强制类型转换;对realloc返回的地址进行判断,防止出现NULL类型
三、常见的动态内存错误
1.对空指针解引用
2.对动态开辟空间的越界访问
3.对非动态开辟的内存空间释放
4.对动态开辟的内存空间部分释放
5.对同一块动态开辟的内存空间多次释放
6.忘记对动态开辟的内存空间释放,造成内存泄漏