当前位置:网站首页>(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,如果我的文章能对您有帮助的话,麻烦各位观众姥爷们点赞、收藏、关注我吧!如果你对我的文章有任何问题或者意见,欢迎在评论区给我留言。后期更多知识点将持续更新......
边栏推荐
- 【Multisim仿真】直流稳压电源设计报告
- CVPR最佳论文得主清华黄高团队提出首篇动态网络综述
- 1004 成绩排名 (20 分)
- 四、Web场景之静态资源配置原理
- 网络ID,广播地址,掩码位数计算
- 教你如何封装功能组件和页面组件
- PoE视频监控解决方案
- It turns out that the MAE proposed by He Yuming is still a kind of data enhancement
- The University of Göttingen proposed CLIPSeg, a model that can perform three segmentation tasks at the same time
- 十、视图解析原理与源码分析
猜你喜欢
随机推荐
十一、拦截器运行原理
[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)
《基于机器视觉的输电线路交叉点在线测量方法及技术方案》论文笔记
LeetCode刷题之第33题
LeetCode刷题之第86题
盘点关于发顶会顶刊论文,你需要知道写作上的这些事情!
【数据库和SQL学习笔记】9.(T-SQL语言)定义变量、高级查询、流程控制(条件、循环等)
五、请求处理—Rest映射是怎样实现的?
【ts】typescript高阶:条件类型与infer
SQL (2) - join window function view
Polygon计算每一个角的角度
Service
【22李宏毅机器学习】课程大纲概述
It turns out that the MAE proposed by He Yuming is still a kind of data enhancement
物联网-广域网技术之NB-IoT
基于STM32F407的WIFI通信(使用的是ESP8266模块)
OSPF故障排除办法
数控直流电源
【ts】typescript高阶:分布式条件类型
【论文阅读-表情捕捉】High-quality Real Time Facial Capture Based on Single Camera









![[Pytorch study notes] 11. Take a subset of the Dataset and shuffle the order of the Dataset (using Subset, random_split)](/img/59/ce3e18f32c40a97631f5ac1b53662a.png)