一. C语言动态内存管理库函数介绍
1.1 为什么存在动态内存管理
我们已经掌握的内存开辟方式有:
int val = 20;//在栈空间上开辟四个字节
char arr[10] = {
0};//在栈空间上开辟10个字节的连续空间
但是上述的开辟空间的方式有两个特点:
-
空间开辟大小是固定的。
-
数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。
但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道,那数组的编译时开辟空间的方式就不能满足了。也就是说当我们在定义变量时并不知道会使用多少的内存,这时候就需要进行动态内存开辟!
上述两种开辟内存方法一个在栈上开辟,一个在堆上开辟。
在C语言<stdlib.h>
或<malloc.h>
内置的库中有能够进行动态内存开辟的库函数。
1.2 动态内存管理函数
🎉malloc
//Allocates memory blocks.
void *malloc( size_t size );
参数size_t size
表示需要开辟的内存的字节数。该函数会返回开辟好内存的首地址,如果开辟失败返回NULL
。
比如使用malloc
函数开辟拥有10
个整型元素的数组,那需要开辟的字节数为40字节。
#include <stdio.h>
#include <stdlib.h>
int main()
{
//使用malloc开辟一个含10个的整型元素数组
int* arr = NULL;
int* p = (int*)malloc(sizeof(int) * 10);//为数组开辟内存
if (p == NULL)
{
printf("内存申请失败!\n");
exit(-1);//内存申请失败,程序没有再进行的必要,直接强制结束程序
}
arr = p;//确认内存开辟成功再将此内存交给数组
p = NULL;
int i = 0;
for (i = 0; i < 10; i++)
{
arr[i] = i + 1;
printf("%d ", arr[i]);
}
return 0;
}
因为malloc
函数的返回值类型为void*
,所以需要将已经开辟好的内存的首地址强制转换成整型指针类型。
运行结果:
1 2 3 4 5 6 7 8 9 10
C:\Users\HP\Desktop\gitee\test\world\test\x64\Debug\test.exe (进程 13104)已退出,代码为 0。
按任意键关闭此窗口. . .
🎉free
对于动态内存开辟的空间,开辟的地址是在堆上的,使用完了是需要返还给操作系统的,C语言中专门有一个回收动态开辟内存的函数——free
。当然,程序结束时,会自动释放内存。
//Deallocates or frees a memory block.
void free( void *memblock );
参数void *memblock
表示动态开辟内存的首地址,注意这个地址只能是动态开辟内存的首地址,其他的地址都不行!如果传入的地址为NULL
,则这个函数什么都不会做。
在上面所举例创建10个整型数组的程序中,就忽略了动态内存的释放,存在内存泄漏的风险。所以正确完整的程序应该为:
参数void *memblock表示动态开辟内存的首地址,注意这个地址只能是动态开辟内存的首地址,其他的地址都不行!如果传入的地址为NULL,则这个函数什么都不会做。
在上面所举例创建10个整型数组的程序中,就忽略了动态内存的释放,存在内存泄漏的风险。所以正确完整的程序应该为:
int main()
{
//使用malloc开辟一个含10个的整型元素数组
int* arr = NULL;
int* p = (int*)malloc(sizeof(int) * 10);//为数组开辟内存
if (p == NULL)
{
printf("内存申请失败!\n");
exit(-1);//内存申请失败,程序没有再进行的必要,直接强制结束程序
}
arr = p;//确认内存开辟成功再将此内存交给数组
p = NULL;
int i = 0;
for (i = 0; i < 10; i++)
{
arr[i] = i + 1;
printf("%d ", arr[i]);
}
free(arr);//有借有还,再借不难
arr = NULL;//好习惯:内存释放后,将指针变量置空
return 0;
}
运行结果:
1 2 3 4 5 6 7 8 9 10
C:\Users\HP\Desktop\gitee\test\world\test\x64\Debug\test.exe (进程 13104)已退出,代码为 0。
按任意键关闭此窗口. . .
🎉内存泄漏的危害:
如果动态内存已经使用完了,但不还给操作系统,也就是没有释放内存,就有可能造成内存泄漏的风险。对于其危害,举个栗子,如果在服务器上存在内存泄漏,则可能造成服务器崩溃。因为服务器是一直工作的,一旦存在内存泄漏,使用完的内存不还回去,久而久之,服务器内存被占用的越来越多,终有一天由于内存不足而造成服务器崩溃。
🎉calloc
该函数功能与malloc
非常相似,仅仅多了个初始化的功能,就是说在动态内存开辟时,自动将内存中的元素初始化为0。
//Allocates an array in memory with elements initialized to 0.
void *calloc( size_t num, size_t size );
参数size_t num
表示元素个数,size_t size
表示每个元素所占字节数大小。
int main()
{
//使用malloc开辟一个含10个的整型元素数组
int* arr