首页 > 系统相关 >动态内存管理

动态内存管理

时间:2024-11-21 18:13:41浏览次数:3  
标签:动态内存 管理 free 内存 数组 空间 函数

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

创建变量的本质是向内存申请空间。

int a=10;————向内存中申请4个字节的空间来存放10这个整型数据。

int arr[10];————在内存中申请一块连续的空间(40个字节)

int math[30];————如果只有20个人,会有10个整型的空间浪费。

                                  如果一共有30个人,则本数组的大小不够。

思考:如果不够用了,可以变大吗?  如果太多了,可以减小吗? ————答案是不能的。

总结:变量和数组的方式不够灵活,两者空间开辟的大小是固定的,数组在创建时必须指明数组长               度指明后就不可再变化。(数组空间一旦指明大小就不可调整)

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

因此C语言引入了动态内存开辟,让程序员可以自己申请和释放空间,就比较灵活了。

其次使用动态内存开辟还可以维护内存的生命周期。

如果直接创建变量,变量出了其作用域之后会自动销毁,4个字节的空间就与本程序无关了。

如果使用动态内存开辟,什么时候释放空间由程序员自己决定,就比较灵活。

二:malloc和free

1.malloc

C语言提供了一个动态内存开辟的函数

这个函数向内存中申请一块连续可用的空间,并返回指向这块空间的指针

注意:

1.如果开辟成功,则返回一个指向开辟好空间起始位置的指针。

2.如果开辟失败(内存不够),则返回空指针NULL,因此malloc函数的返回值一定要做检查。

3.由于此函数并不知道你申请这块空间用来存储什么类型的数据,因此返回值是void*,具体在使       用时自己决定。

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

2.free

C语言提供了另外一个函数free,专门用来做动态内存的回收。

注意:

1.如果参数ptr指向的空间不是动态开辟的,那free函数的行为是未定义的

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

3.malloc和free以及后面的calloc和realloc都声名在stdlib.h头文件中。

4.malloc  calloc  realloc 一定要与free成对使用(这是一个很好的编程习惯)否则可能引发一些后     果。

5.如果程序退出的时候,即使没有free操作系统也会主动回收动态开辟的空间,但是程序如果不退     出就要小心。

malloc和free的使用案例:

思考:程序的最后使p置为NULL有没有必要?

三:calloc和realloc

1.calloc

C语言还提供了一个函数叫calloc,calloc函数与malloc类似,也用来动态内存开辟。

注意:

1.函数的功能是为num个大小为size的元素开辟一块空间,并且把空间的每个字节初始化为0.

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

所以如果我们对申请空间的内容要求初始化,那么可以使用calloc很方便的完成任务。

2.realloc

C语言提供了realloc函数用来对动态内存的大小进行调整。

注意:

1.ptr是要调整的内存地址。

2.size是调整之后动态内存的大小。

3.函数的返回值是调整之后的内存起始位置。

4.这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间。

5.realloc(NULL,40);等价于malloc(40);

   情况一:原有空间之后有足够大的空间。

                 这种情况下新申请到的空间直接在原有内存之后追加,原来内存空间数据不会变化。

   情况二:原有空间之后没有足够大的空间。

                 这种情况下会在堆空间中另找一个合适的连续空间来使用,这样函数会返回一个新地址。

realloc函数使用案例:

这段代码中不能直接用原来空间地址p来接受realloc的返回值,因为realloc函数也是有可能空间开辟失败的。

四:使用动态内存时常见的错误分析

1.对NULL指针的解引用操作:

本程序中由于开辟的空间过大,内存不足,无法成功开辟,就会返回空指针NULL,形成对空指针的解引用。就会出现问题。

启示:对于动态内存开辟函数的返回值一定要检查是否为空指针。

一道经典的笔试题:

本程序运行之后什么都不打印,最终程序会崩溃,

原因在于str仍然是空指针,strcpy实现的过程中一定会有对str的解引用操作,对空指针解引用是非法的,会报警告。

2.对动态开辟空间的越界访问(非法访问):

非法访问相关的一道笔试题

请问程序的运行结果是什么?

解析:本题目运行结果是未知的,当第一个函数执行结束后p【】数组也会销毁(生命周期结束)

           (p数组这块空间已经不属于当前程序了,还是不是hello world就不好确定了)。

           再想要找回p数组中的元素(printf函数要通过str去找p数组中的字符,找到一个打印一个)             已经不可能了,(但如果幸运的话,也有可能打印出hello  world)

这道笔试题就类似于:

3.对非动态开辟内存使用free释放:

对非动态内存使用free释放系统会崩溃,因为非动态内存使用free函数,free函数的行为是未定义的。

4.使用free释放动态内存开辟的一部分(提前释放):

相关笔试题:

这个程序在结束之前就使用free函数释放了动态内存。

且这个程序在使用free函数之后没有将str置NULL,str的值是不确定的,就会形成野指针。

(找不到之前hello的空间了)。

free函数使用完一定要有一个p=NULL的操作。

5.对同一块动态内存多次释放:

free(p)执行之后,p不再指向动态申请空间内存的地址。

p的指向位置,再次使用free(p)就会有危险。

启示:在使用free(p)之后,一定要有p=NULL的操作。这是一个好的编程习惯。

6.动态开辟内存忘记释放(内存泄漏):

忘记释放不再使用的动态开辟的空间会造成内存泄漏

启示:动态内存开辟的空间最后一定要释放,并且要正确释放。

相关笔试题:

这个程序没有释放开辟的动态内存,造成了内存泄漏。

没有释放,程序本身也找不到它了。

假如有一个服务器上的程序7*24小时运行,每过一星期内存就会耗干,程序挂掉,重启之后又可以运行,一周之后又挂掉————大概率是内存泄露了。

五:柔性数组

柔性数组其实就是指结构体中的最后一个数组成员

这个成员的大小是未知的

本程序结构体中的最后一个数组成员大小未知,是柔性数组成员。

柔性数组的特点:

1.柔性数组成员前必须至少有一个其他成员。

2.sizeof返回时不包含柔性数组的大小。

3.包含柔性数组成员的的结构体要用malloc函数进行内存动态分配,提前适应内存大小。

柔性数组大概实现了变长数组的功能。

柔性数组使用举例:

使用方法二:

柔性数组的优势:

七:C/C++中程序内存区域划分

完.

标签:动态内存,管理,free,内存,数组,空间,函数
From: https://blog.csdn.net/2403_88695928/article/details/143918910

相关文章

  • Homebrew 使用指南:为开发者和日常用户量身定制的包管理器
    Homebrew是macOS和Linux平台上强大的包管理工具,它让软件的安装、更新和卸载变得简单而优雅。如果你是开发者或想高效管理工具,这篇指南将帮助你快速上手并掌握Homebrew的使用技巧。1.什么是Homebrew?Homebrew是一个包管理器,它的核心目标是“让缺少的东西变得简单......
  • linux之磁盘管理
    磁盘管理1.磁盘分类机械硬盘:盘片主轴传动手臂做机械运动类似DVD固态硬盘:内部是主板和U盘类似2.硬盘大小3.5英寸:台式机2.5英寸:笔记本服务器3.硬盘接口IDE接口过时scsi接口过时sata接口台式机3.0nvme接口固态硬盘SAS接口企业级4.硬盘存储......
  • 如何通过习惯养成提升专注力和效率?项目管理软件给你答案!
    成就感驱动:化繁为简,激发内在动力成就感的心理学基础根据心理学家阿尔伯特·班杜拉的自我效能理论,成就感来自于“实现目标”的直接体验。这种体验既能增强人们对自己能力的信心,也会让人产生继续努力的动机。在工作中,项目的成功往往依赖于一系列小目标的达成,而每个小目标的实现......
  • springboot毕设高校线上选课管理系统源码+论文+部署
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、研究背景随着高校规模的不断扩大和信息技术的飞速发展,传统的选课方式已难以满足现代高校教学管理的需求。在传统模式下,选课过程往往依赖于人工操作,如纸质......
  • TSINGSEE青犀新能源充电桩智能管理方案:如何利用AI解决充电难停车难的问题?
    随着新能源汽车产业的迅猛发展,充电桩的安全问题日益凸显,成为制约行业健康发展的重要因素。近年来频发的自燃事件不仅给车主带来了财产损失,也对公众的安全感构成了挑战。因此,利用先进的AI技术和图像识别算法,构建充电桩安全监测体系显得尤为重要。国标GB28181视频平台EasyCVR作为TS......
  • 绩效管理体系的设计方法有哪些?
    绩效管理体系的设计方法有很多,常用的有以下几种:关键绩效指标法(KPI):根据组织的战略目标,确定关键成功领域、关键绩效要素和关键绩效指标,构建组织、部门和个人的KPI库,进行定量和定性的评估。平衡计分卡法(BSC):根据组织的愿景和战略,从财务、客户、内部流程和学习成长四个角度,制定战略......
  • Go的依赖管理
    Go依赖管理Go的依赖管理经历了3个阶段,由于历史原因,目前普遍使用的是Gomod做依赖管理但是了解过去的依赖管理的优缺点,便于我们理解Gomod的设计第一阶段:  Go Path阶段:使用简单,但是由于GoPath的依赖管理只是根据路径来做区分,无法做多版本管理  因此多个项目如果依赖......
  • icacls 是 Windows 操作系统中用于管理文件和目录的访问控制列表(ACL)命令行工具。它可
    icacls|MicrosoftLearnicacls是Windows操作系统中用于管理文件和目录的访问控制列表(ACL)命令行工具。它可以用来查看、修改、备份和恢复文件和文件夹的权限设置。权限控制是Windows安全体系的重要组成部分,icacls是在命令行下管理这些权限的一种方式。1.什么是 icacls?......
  • flask毕设春华纺织厂的仓储管理系统(论文+程序)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容选题背景在纺织行业中,仓储管理是影响生产效率、成本控制和客户满意度的关键环节。春华纺织厂作为行业内的一员,面临着日益增长的仓储管理需求与挑战......
  • 利用 Python 和 Selenium 高效启动和管理 Chrome 浏览器
    在自动化测试和网页抓取的过程中,Selenium是最常用的工具之一。其强大的功能可以与浏览器无缝集成,实现复杂的操作。然而,为了提高效率和扩展性,尤其在处理大量任务时,我们可以通过定制化的方法启动Chrome浏览器并与Selenium驱动连接。本文将详细解析两段关键代码,实现以下目标:......