C语言提供了相关的动态内存分配函数,需要多大内存空间就分配多大内存空间,并且可以动态调整已分配的内存空间大小
使用下面相关动态内存函数需要引用头文件
malloc函数功能:
向内存申请指定大小的连续内存空间,申请成功返回该空间起始地址,申请失败返回NULL指针
库函数malloc声明
void* malloc (size_t size);
返回值:申请成功返回该空间起始地址,申请失败返回NULL指针,因为不知道申请的空间要存放什么类型数据所以返回void*类型
size: 申请分配的内存大小,单位为字节
注意:
1. malloc返回值有可能是NULL指针,使用前需要检查
2. malloc申请的空间并没有被初始化
free函数功能:
释放申请的动态内存分配的空间(即malloc、calloc、realloc函数申请的空间)
库函数free声明
void free (void* ptr);
ptr : 指向先前用malloc、calloc或realloc分配的内存块的指针
注意:
1.如果 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的
2. 如果ptr 是NULL指针,则函数什么事都不做
3. 只会释放ptr指向空间的值,但ptr本身不会被置空
#include
#include
int main()
{
//申请10个int类型大小空间,10 * sizeof(int)相对于sizeof(40)更具有移植性
//由于malloc返回值为void*类型,所以强制类型转换为int*类型
int* p = (int*)malloc(10 * sizeof(int));
if (p == NULL) //空间申请失败则退出
{
return -1;
}
int i = 0;
for (i = 0; i < 10; i++) //打印这10个元素
{
printf("%d ", *(p + i));
}
printf("\n");
for (i = 0; i < 10; i++) //对数组元素赋值
{
*(p + i) = i;
}
for (i = 0; i < 10; i++) //打印这10个元素
{
printf("%d ", *(p + i));
}
printf("\n");
free(p); //释放p所指向动态内存分配的空间
p = NULL;//将p置为NULL指针,防止访问一个已释放的空间
return 0;
}
输出
-842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451
0 1 2 3 4 5 6 7 8 9
calloc函数功能:
calloc函数与malloc函数功能一样,区别主要在于calloc会对分配的空间初始化为0,另外它们请求内存大小的方式不同
库函数calloc声明
void* calloc (size_t num, size_t size);
返回值:申请成功返回该空间起始地址,申请失败返回NULL指针,因为不知道申请的空间要存放什么类型数据所以返回void*类型
num:元素个数
size: 元素大小
申请内存空间大小=num*size
#include
#include
int main()
{
int* p = (int*)calloc(10,sizeof(int));
if (p == NULL) //空间申请失败则退出
{
return -1;
}
int i = 0;
for (i = 0; i < 10; i++) //打印这10个元素
{
printf("%d ", *(p + i));
}
printf("\n");
for (i = 0; i < 10; i++) //对数组元素赋值
{
*(p + i) = i;
}
for (i = 0; i < 10; i++) //打印这10个元素
{
printf("%d ", *(p + i));
}
printf("\n");
free(p); //释放p所指向动态内存分配的空间
p = NULL;//将p置为NULL指针,防止访问一个已释放的空间
return 0;
}
输出
0 0 0 0 0 0 0 0 0 0
0 1 2 3 4 5 6 7 8 9
使用malloc还是calloc函数取决是否要对动态内存分配的空间初始化
realloc函数功能:
realloc对动态内存空间大小进行扩大或缩小
库函数realloc声明
void* realloc (void* ptr, size_t size);
返回值:返回调整后空间的起始地址,调整失败返回NULL指针
ptr:指向先前用malloc、calloc或realloc分配的内存块的指针
size:动态内存空间新大小,单位为字节
#include
#include
int main()
{
int* p = (int*)malloc(10 * sizeof(int));
if (p == NULL) //空间申请失败则退出
{
return -1;
}
int i = 0;
for (i = 0; i < 10; i++) //对数组元素赋值
{
*(p + i) = i;
}
int* ptr = (int*)realloc(p, 20 * sizeof(int)); //对动态内存大小进行调整
if (ptr == NULL) //调整失败并不影响原本p指向空间
{
printf("空间调整失败\n");
}
else
{
p = ptr; //调整成功,p指向调整后空间起始地址
ptr = NULL;
for (i = 10; i < 20; i++) //对数组元素赋值
{
*(p + i) = i;
}
for (i = 0; i < 20; i++) //打印数组元素
{
printf("%d ", *(p + i));
}
}
free(p); //释放p所指向动态内存分配的空间
p = NULL;//将p置为NULL指针,防止访问一个已释放的空间
return 0;
}
输出
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#include
#include
int main()
{
int* p = (int*)malloc(100000000000000000 * sizeof(int));
*p = 10; //没有对p是否非NULL检查
return 0;
}
申请动态内存分配失败,p为NULL指针,对p解引用修改存储的值会错误
#include
#include
int main()
{
int* p = (int*)malloc(10 * sizeof(int));
if (p == NULL)
{
return -1;
}
int i = 0;
for (i = 0; i <= 10; i++)
{
*(p+i) = i;
}
free(p);
p = NULL;
return 0;
}
当i=10,*(p+i)越界访问了
#include
#include
int main()
{
int i = 10;
int* p = &i;
free(p);
p = NULL;
return 0;
}
p指向空间不是动态内存分配的空间
#include
#include
int main()
{
int* p = (int*)malloc(10 * sizeof(int));
if (p == NULL)
{
return -1;
}
free(p+5);
p = NULL;
return 0;
}
p+5指向空间是动态内存分配的空间的一部分
#include
#include
int main()
{
int* p = (int*)malloc(10 * sizeof(int));
free(p);
*p = 10; //对已经free的动态内存分配空间访问
free(p);//对动态内存分配空间多次free释放
p = NULL;
return 0;
}
当申请的动态内存空间不需要时应该被释放,这样可以重新分配使用。申请的空间在使用完毕后不free释放将引起内存泄漏。内存泄漏将一点点榨干可用内存,最终导致系统崩溃
#include
#include
void test()
{
int* p = (int*)malloc(10*sizeof(int));
}
int main()
{
while(1)
{
test();
//业务处理,满足条件则退出while循环
}
return 0;
}
当业务处理没有满足条件则while为死循环,每次循环都会申请内存空间,最终将系统崩溃