动态内存管理

简介: 动态内存管理

一、为什么要有动态内存分配

       我们在写代码时,编译器都会自动为我们分配空间,但会有这么两个特点:

        空间开辟⼤⼩是固定的。

       数组在申明的时候,必须指定数组的⻓度,数组空间⼀旦确定了⼤⼩不能调整。

       但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间⼤⼩在程序运⾏的时候才能知道,那数组的编译时开辟空间的⽅式就不能满⾜了。

        C语⾔引⼊了动态内存开辟,让程序员⾃⼰可以申请和释放空间,就⽐较灵活了。

二、动态内存开辟的函数

       2.1 malloc函数

void* malloc (size_t size);

       这个函数向内存申请⼀块连续可⽤的空间,并返回指向这块空间的指针。

        如果开辟成功,则返回⼀个指向开辟好空间的指针。

       如果开辟失败,则返回⼀个 NULL 指针,因此malloc的返回值⼀定要做检查。

        返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使⽤的时候使⽤者⾃ ⼰来决定。

       如果参数 size 为0,malloc的⾏为是标准是未定义的,取决于编译器。  

        2.2 calloc函数

void* calloc (size_t num, size_t size);

       函数的功能是为 num 个⼤⼩为 size 的元素开辟⼀块空间,并且把空间的每个字节初始化为0。

       与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。

       2.3 realloc函数

void* realloc (void* ptr, size_t size);

        realloc函数的出现让动态内存管理更加灵活。

        有时会我们发现过去申请的空间太⼩了,有时候我们⼜会觉得申请的空间过⼤了,那为了合理的时 候内存,我们⼀定会对内存的⼤⼩做灵活的调整。那 realloc 函数就可以做到对动态开辟内存⼤ ⼩的调整。

       realloc在调整内存空间的是存在两种情况:

       情况1:原有空间之后有⾜够⼤的空间

       情况2:原有空间之后没有⾜够⼤的空间

      情况1

       当是情况1 的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发⽣变化。

       情况2

       当是情况2 的时候,原有空间之后没有⾜够多的空间时,扩展的⽅法是:在堆空间上另找⼀个合适⼤⼩ 的连续空间来使⽤。这样函数返回的是⼀个新的内存地址。

三、内存释放函数

       学习完内存开辟函数后,我们随后会来学习内存释放函数。那我们为什么要学习内存释放函数呢?内存开辟函数就是向内存中借一块空间,俗话说:有借有还。所以,我们要来学习内存释放函数来进行归还。所以在学习前记住一句话:只要开辟就要释放。

void free (void* ptr);

       内存释放函数为free函数,如果参数 ptr 指向的空间不是动态开辟的,那free函数的⾏为是未定义的。

       如果参数 ptr 是NULL指针,则函数什么事都不做。

四、柔性数组

       柔性数组是什么?相信看到这你有点小懵,难道会柔道的数组称之为柔性数组?非也。柔性数组为结构体中定义的处于结构体最后一个成员的数组(最好不要定义其大小,有的编译器会报错)。

1. typedef struct s
2. {
3.  int a;
4.  int arr[];
5. };

       柔性数组的特点:

       柔性数组的前面必须包含其他结构体成员。

       sizeof求其结构体大小时不会包含柔性数组的大小。

       使用malloc为柔性数组开辟空间时,要大于结构体的大小以符合柔性数组的期待。

        用法如下:

1. 
2. #include<stdio.h>
3. typedef struct s
4. {
5.  int a;
6.  int arr[];
7. }type_a;
8. int main()
9. {
10.   int a = 0;
11.   type_a* p = (type_a*)(malloc(sizeof(type_a) + 100 * sizeof(int)));
12.   p->a = 100;
13.   for (int i = 0; i < 100; i++)
14.   {
15.     p->arr[i] = i;
16.   }
17.   free(p);
18.   p = NULL;
19.   return 0;
20. }
21. 
22.

五、 经典例题

1. #include<stdio.h>
2. #include<stdlib.h>
3. void GetMemory(char* p)
4. {
5.  p = (char*)malloc(100);
6. }
7. void Test(void)
8. {
9.  char* str = NULL;
10.   GetMemory(str);
11.   strcpy(str, "hello world");
12.   printf(str);
13. }

       以上代码运行会有什么后果?

       本题意图为为str开辟出一块空间,对吧?但是,在函数中p为局部变量,运行结束时会销毁,所以,它的地址传不回来,就会开辟失败。但,即使开辟成功,仍有问题,这是为什么呢?咱们在开始时,说过了要有借有还,所以应该要对其进行内存释放,否则,会造成内存泄漏。

1. #include<stdio.h>
2. #include<stdlib.h>
3. void Test(void)
4. {
5.  char* str = (char*)malloc(100);
6.  strcpy(str, "hello");
7.  free(str);
8.  if (str != NULL)
9.  {
10.     strcpy(str, "world");
11.     printf(str);
12.   }
13. }

        以上代码运行会有什么后果?

       在str开辟完空间后,又对其释放,那str能打印出来吗?答案是:不一定。为什么?内存不是没了吗?那里面存放的理应没了呀?对吧。其实,你可以这样理解:你在酒店开了个房间,第二天为了赶火车,不小心把身份证落下了,如果此时房间还没有被打扫,你还能在原位置找到,对吧?打扫了就不能在原位置找到了对吧?理解了我举得例子,相信你就理解了打印结果的情况。

       完!

相关文章
|
1天前
|
云安全 监控 安全
|
6天前
|
机器学习/深度学习 人工智能 自然语言处理
Z-Image:冲击体验上限的下一代图像生成模型
通义实验室推出全新文生图模型Z-Image,以6B参数实现“快、稳、轻、准”突破。Turbo版本仅需8步亚秒级生成,支持16GB显存设备,中英双语理解与文字渲染尤为出色,真实感和美学表现媲美国际顶尖模型,被誉为“最值得关注的开源生图模型之一”。
820 5
|
12天前
|
人工智能 Java API
Java 正式进入 Agentic AI 时代:Spring AI Alibaba 1.1 发布背后的技术演进
Spring AI Alibaba 1.1 正式发布,提供极简方式构建企业级AI智能体。基于ReactAgent核心,支持多智能体协作、上下文工程与生产级管控,助力开发者快速打造可靠、可扩展的智能应用。
1051 37
|
8天前
|
机器学习/深度学习 人工智能 数据可视化
1秒生图!6B参数如何“以小博大”生成超真实图像?
Z-Image是6B参数开源图像生成模型,仅需16GB显存即可生成媲美百亿级模型的超真实图像,支持中英双语文本渲染与智能编辑,登顶Hugging Face趋势榜,首日下载破50万。
620 36
|
12天前
|
人工智能 前端开发 算法
大厂CIO独家分享:AI如何重塑开发者未来十年
在 AI 时代,若你还在紧盯代码量、执着于全栈工程师的招聘,或者仅凭技术贡献率来评判价值,执着于业务提效的比例而忽略产研价值,你很可能已经被所谓的“常识”困住了脚步。
677 57
大厂CIO独家分享:AI如何重塑开发者未来十年
|
8天前
|
存储 自然语言处理 测试技术
一行代码,让 Elasticsearch 集群瞬间雪崩——5000W 数据压测下的性能避坑全攻略
本文深入剖析 Elasticsearch 中模糊查询的三大陷阱及性能优化方案。通过5000 万级数据量下做了高压测试,用真实数据复刻事故现场,助力开发者规避“查询雪崩”,为您的业务保驾护航。
429 27
|
15天前
|
数据采集 人工智能 自然语言处理
Meta SAM3开源:让图像分割,听懂你的话
Meta发布并开源SAM 3,首个支持文本或视觉提示的统一图像视频分割模型,可精准分割“红色条纹伞”等开放词汇概念,覆盖400万独特概念,性能达人类水平75%–80%,推动视觉分割新突破。
911 59
Meta SAM3开源:让图像分割,听懂你的话
|
5天前
|
弹性计算 网络协议 Linux
阿里云ECS云服务器详细新手购买流程步骤(图文详解)
新手怎么购买阿里云服务器ECS?今天出一期阿里云服务器ECS自定义购买流程:图文全解析,阿里云服务器ECS购买流程图解,自定义购买ECS的设置选项是最复杂的,以自定义购买云服务器ECS为例,包括付费类型、地域、网络及可用区、实例、镜像、系统盘、数据盘、公网IP、安全组及登录凭证详细设置教程:
200 114