一.为什么要有动态内存管理
二.malloc和free
malloc函数———动态申请内存
基础概念 :头文件<stdlib.h>
应用方法
#include <stdio.h>
#include<stdlib.h>
int main()
{
//开辟40个字节的内存空间,将空间首地址指向p
int* p = (int*)malloc(40);
//判断申请内存空间是否成功
if (p == NULL)
{
perror("malloc");
return 1;
}
int i = 0;
//给开辟的空间赋值
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
//输出内容
for (i = 0; i < 10; i++)
{
printf("%d ",*(p+i));
}
return 0;
}
#include <stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)malloc(4000000000000000);
//判断申请内存空间是否成功
if (p == NULL)
{
perror("malloc");
return 1;
}
int i = 0;
//给开辟的空间赋值
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
//输出内容
for (i = 0; i < 10; i++)
{
printf("%d ",*(p+i));
}
return 0;
}
free函数——接收内存首地址,释放动态申请的内存。
基础概念:头文件:<stdlib.h>
应用
#include <stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)malloc(40);
//判断申请内存空间是否成功
if (p == NULL)
{
perror("malloc");
return 1;
}
int i = 0;
//给开辟的空间赋值
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
//输出内容
for (i = 0; i < 10; i++)
{
printf("%d ",*(p+i));
}
//释放内存
free(p);
//为了避免p指向的空间无意义,成为野指针,将p赋值为空;
p = NULL;
return 0;
}
三.calloc和realloc
calloc函数=malloc+将申请的内存中每个字节初始化为0
基础概念
应用
#include <stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)calloc(10,sizeof(int));
//判断申请内存空间是否成功
if (p == NULL)
{
perror("malloc");
return 1;
}
int i = 0;
//输出内容
for (i = 0; i < 10; i++)
{
printf("%d ",*(p+i));
}
//释放内存
free(p);
//为了避免p指向的空间无意义,成为野指针,将p赋值为空;
p = NULL;
return 0;
}
realloc函数 ——动态调整动态内存大小
基础概念
应用
#include <stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)calloc(10,sizeof(int));
//判断申请内存空间是否成功
if (p == NULL)
{
perror("malloc");
return 1;
}
int i = 0;
//输出内容
for (i = 0; i < 10; i++)
{
printf("%d ",*(p+i));
}
//内存不够,扩大到20个整形大小
int* ptr=realloc(p, 20 * sizeof(int));
//如果修改内存成功,则把新内存的首地址指向p
if (ptr != NULL)
{
p = ptr;
}
//释放内存
free(p);
//为了避免p指向的空间无意义,成为野指针,将p赋值为空;
p = NULL;
return 0;
}
调整内存失败和成功后出现的结果
realloc也可以当做malloc来用
#include <stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)realloc(NULL,10*sizeof(int));
//判断申请内存空间是否成功
if (p == NULL)
{
perror("malloc");
return 1;
}
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
//输出内容
for (i = 0; i < 10; i++)
{
printf("%d ",*(p+i));
}
//释放内存
free(p);
//为了避免p指向的空间无意义,成为野指针,将p赋值为空;
p = NULL;
return 0;
}
四.常见的动态内存的错误
1.对NULL指针的解引用操作
#include <stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)malloc(40);
//如果内存申请失败,则p有可能是空指针,空指针不可解引用
*p = 20;
free(p);
return 0;
}
2.对动态开辟空间的越界访问
#include <stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)malloc(40);
if (p == NULL)
{
perror("malloc");
return 1;
}
int i;
for (i = 0; i <= 10; i++)//开辟了十个整形的大小,访问到第十一个时越界
{
*(p + i) = i;
}
free(p);
p = NULL;
return 0;
}
3.对非动态开辟内存使用free释放
#include <stdio.h>
#include<stdlib.h>
int main()
{
int a = 10;
int* p = (int*)malloc(40);
if (p == NULL)
{
perror("malloc");
return 1;
}
p = &a;
//此时p指向的不再是动态申请的内存
free(p);
//无法释放非动态申请的内存
p = NULL;
return 0;
}
4.使用free释放一块动态开辟内存的一部分
#include <stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)malloc(40);
if (p == NULL)
{
perror("malloc");
return 1;
}
p++;
//此时p指向的已经不是内存的首地址了,只能释放其中的一部分内存
//报错
free(p);
p = NULL;
return 0;
}
5.对同一块动态内存多次释放
#include <stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)malloc(40);
if (p == NULL)
{
perror("malloc");
return 1;
}
free(p);
//对同一块内存重复释放,对不存在的内存进行释放,报错
free(p);
p = NULL;
return 0;
}
6.动态开辟内存忘记释放(内存泄露)
#include <stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)malloc(40);
if (p == NULL)
{
perror("malloc");
return 1;
}
//申请的内存由于死循环永远无法释放,导致内存泄露
while (1);
free(p);
p = NULL;
return 0;
}