当前位置:网站首页>(C语言)动态内存管理
(C语言)动态内存管理
2022-08-05 05:17:00 【Captain林】
本篇文章计划用最简单的方式向大家介绍C语言动态内存管理这一问题
如果各位看官姥爷们觉得有用的话,不妨动动你们手指,点赞、评论、收藏哦!
目录
1.为什么需要动态内存分配
我们常见的内存开辟方式有:
int a = 20;//在栈空间上开辟四个字节
char arr[10] = { 0 };//在栈空间上开辟10个字节的连续空间
上述内存开辟方式有两个特点:
1. 空间开辟大小是固定的。2. 数组必须指定数组的长度,以获取所需内存。
但是我们对于空间的需求,不仅仅是上述的情况。有时候我们需要根据情况来决定开辟空间的大小
此时动态内存的作用就凸显出来了
2.动态内存的介绍
2.1malloc和free
void* malloc(size_t size);
这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。
- 如果开辟成功,则返回一个指向开辟好空间的指针。
- 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
- 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
- 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。
void free(void* ptr);
C语言提供了另外一个函数free,专门是用来做动态内存的释放和回收
话不多说,直接上代码
int main()
{
int arr[40] = {0};
int* prt = (int*)malloc(40);//申请空间
//检查
if (prt == NULL)
{
perror("malloc");//检查错误的函数,要使用双引号,检查的是开辟空间的malloc
return 1;
}
//初始化
int i = 0;
for (i = 0; i < 10; i++)
{
*(prt + 1) = i;
}
//释放空间
free(prt);//这里释放的是地址,因此不需要解引用
prt = NULL;
return 0;
}
2.2calloc
C语言还提供了一个函数叫 calloc , calloc 函数也用来动态内存分配,其具体使用我们结合下面一个函数来讲解
- 与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0
void* calloc(size_t num, size_t size);
2.3realloc
- realloc函数的出现让动态内存管理更加灵活。
- 当我们发现过去申请的空间太小或太大,那为了合理的使用内存,我们可以使用realloc 函数实现对动态开辟内存大小的调整。
void* realloc(void* ptr, size_t size);
话不多说,让我们一起来看一下calloc和realloc代码的实现吧
int main()
{
//申请空间
//calloc需要两个参数(元素、每个元素类型的大小)
//且在申请之初就会初始化空间为0
int* ptr = (int*)calloc(10, sizeof(int));//ptr必须是指针
//检查
if (ptr == NULL)
{
perror("calloc");//打印错误
return 1;
}
//打印
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", *(ptr + i));
}
//释放空间
//free(calloc);
//假设空间不够,需要扩容20个元素
//原内存空间不够会重新寻找一块空间,将原有内存剪切到新的大空间上,并且把原空间释放
int *p = (int*)realloc(ptr, 80);//20个整形需要80个字节
if (*p != NULL)//防止内存不够,返回空指针
{
ptr = p;
}
//扩容成功
free(ptr);
ptr = NULL;
return 0;
}
3.常见的动态内存使用错误
3.1对空指针的解引用操作
即没有判空,在malloc等函数申请空间是有可能会申请到空指针;
解决方法:判空
3.2对动态空间进行越界访问
解决方法:弄清楚动态内存的边界
for (i = 0; i <= 10; i++)//原申请空间<10,超过10会出现越界访问
{
printf("%d ", *(ptr + i));
}
3.3 对非动态开辟空间使用free
必须在动态开辟空间的起始位置进行释放,否则可能会造成内存泄露(只申请,不归还)
3.4使用free释放动态内存的一部分
3.5对同一静态内存的多次释放
3.6忘记释放空间
4.经典笔试题练手
4.1练习一
void GetMemory(char* p) //这里的指针p在函数结束之后就销毁了,没有将地址返回到Test函数中
{
p = (char*)malloc(100);
}
void Test(void) {
char* str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}
4.2练习二
char* GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char* str = NULL;
str = GetMemory();//虽然str获取到了字符串的地址,但是由于上函数的销毁,原空间也不存在了,无法在进行访问
printf(str);
}
4.3练习三
void GetMemory(char** p, int num)
{
*p = (char*)malloc(num);
}
void Test(void) {
char* str = NULL;
GetMemory(&str, 100);//如果不取地址将无妨修改str
strcpy(str, "hello");
printf(str);
//忘记释放空间
//free(str);
//str = NULL;
}
4.4练习四
void Test(void)
{
char* str = (char*)malloc(100);
strcpy(str, "hello");
free(str);
//str = NULL;//可以通过设置空指针避免此类问题
if (str != NULL)
{
strcpy(str, "world");//free已经将空间还给操作系统了,这里的修改是非法修改
printf(str);
}
}
5.结语
看到这里,相信老铁们对动态内存管理的知识已经有了基本的了解。
我是计算机海洋的新进船长Captain_ldx,如果我的文章能对您有帮助的话,麻烦各位观众姥爷们点赞、收藏、关注我吧!如果你对我的文章有任何问题或者意见,欢迎在评论区给我留言。后期更多知识点将持续更新......
边栏推荐
- It turns out that the MAE proposed by He Yuming is still a kind of data enhancement
- 【数据库和SQL学习笔记】6.SELECT查询4:嵌套查询、对查询结果进行操作
- 关于使用QML的MediaPlayer实现视频和音频的播放时遇到的一些坑
- 初识机器学习
- LeetCode刷题之第54题
- 深度学习系列(一)简介、线性回归与成本函数
- 【数据库和SQL学习笔记】8.SQL中的视图(view)
- 【Pytorch学习笔记】11.取Dataset的子集、给Dataset打乱顺序的方法(使用Subset、random_split)
- IJCAI 2022|边界引导的伪装目标检测模型BGNet
- tensorflow的session和内存溢出
猜你喜欢
LeetCode刷题之第55题
CVPR2021 - Inception Convolution with Efficient Dilation Search
发顶会顶刊论文,你应该这样写作
LeetCode刷题之第61题
【Pytorch学习笔记】10.如何快速创建一个自己的Dataset数据集对象(继承Dataset类并重写对应方法)
七、请求处理——Map、Model类型参数处理原理
LeetCode刷题之第86题
【Kaggle项目实战记录】一个图片分类项目的步骤和思路分享——以树叶分类为例(用Pytorch)
【数据库和SQL学习笔记】10.(T-SQL语言)函数、存储过程、触发器
Facial Motion Capture 调研
随机推荐
二、自动配置之底层注解
1008 数组元素循环右移问题 (20 分)
1004 成绩排名 (20 分)
GIS面试问题
关于使用QML的MediaPlayer实现视频和音频的播放时遇到的一些坑
【数据库和SQL学习笔记】4.SELECT查询2:排序(ORDER BY)、聚合函数、分组查询(GROUP BY)
基于STM32F407的一个温度传感器报警系统(用的是DS18B20温度传感器,4针0.96寸OLED显示屏,并且附带日期显示)
Redis集群(docker版)——从原理到实战超详细
Polygon计算每一个角的角度
HuiFer 带你读懂 BeanFactory getBean 方法
发顶会顶刊论文,你应该这样写作
Thread handler handle IntentServvice handlerThread
九、响应处理——内容协商底层原理
【数据库和SQL学习笔记】6.SELECT查询4:嵌套查询、对查询结果进行操作
[Pytorch study notes] 9. How to evaluate the classification results of the classifier - using confusion matrix, F1-score, ROC curve, PR curve, etc. (taking Softmax binary classification as an example)
You should write like this
CVPR 2022 |节省70%的显存,训练速度提高2倍
【Pytorch学习笔记】9.分类器的分类结果如何评估——使用混淆矩阵、F1-score、ROC曲线、PR曲线等(以Softmax二分类为例)
LeetCode刷题之第129题
【ts】typescript高阶:键值类型及type与interface区别