首页 > 系统相关 >C之动态内存管理(动态内存开辟与调整等)

C之动态内存管理(动态内存开辟与调整等)

时间:2024-06-05 19:58:25浏览次数:28  
标签:malloc 函数 free 内存 动态内存 开辟 调整

目录

1.为什么要有动态内存分配

2.malloc、calloc、realloc和free

malloc:

calloc:

realloc:

free:

3.常见的动态内存的错误

3.1:对NULL指针的解引用操作

3.2:对动态开辟空间的越界访问

3.3:对非动态开辟的内存使用free函数释放

3.4:使用free释放一块动态开辟内存的一部分

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

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

4.柔性数组

柔性数组的特点

柔性数组的优势

5.总结C/C++中程序内存区域划分


我们已经掌握的内存开辟方式有:

int a = 20; ——在栈空间上开辟四个字节

char arr[100] = {0}; ——在栈空间上开辟100个字节的连续空间

其他如“double x = 1.0”、“int arr[50] = {0}”等内存开辟方式本质上跟上面两种是相同的。

那么我们既然已经有了上述两种开辟内存的方式,为什么还要开辟动态内存呢?

这就引出了我们的下文:

1.为什么要有动态内存分配

上文中我们已经讲过了我们已经掌握的两种内存开辟方式,它们有两个特点:

  • 空间开辟大小是固定的
  • 数组在申明时必须指定数组长度,数组大小一旦确定了就不能调整

但是上面往往不能满足我们对于空间的需求,有时候我们需要申请的空间大小往往在运行时才能知道,那数组在编译时开辟空间的方式就无法满足我们的需求了。

因此C语言引入了动态内存开辟,让我们可以自己申请开辟、调整和释放空间。

2.malloc、calloc、realloc和free

:以下四个函数都需要包含头文件<stdlib.h>.

malloc:

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

函数原型如下(malloc - C++ Reference (cplusplus.com)):

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

如图:

  • 如果开辟成功,则返回⼀个指向开辟好空间的指针。
  • 如果开辟失败,则返回⼀个 NULL 指针,因此malloc的返回值⼀定要做检查。
  • 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使⽤的时候使⽤者自己来决定
  • 如果参数 size 为0,malloc的⾏为是标准是未定义的,取决于编译器。

calloc:

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

函数原型如下(calloc - C++ Reference (cplusplus.com)):

  • 函数的作用是为num个大小为size的元素开辟一块空间,并把空间的每个字节都初始化为0
  • 与函数malloc的区别只在于calloc在返回地址之前会把每个字节都初始化为0

因此,我们可以将calloc当作malloc使用,特别是在申请的空间要求初始化时最好用calloc。

realloc:

realloc函数就是用来对动态开辟内存的大小进行调整的

函数原型如下(realloc - C++ Reference (cplusplus.com)):

  • ptr 是要调整的内存地址(即动态开辟内存后返回的地址)
  • size为调整之后的新大小(单位为字节)
  • 返回值为调整之后的内存起始位置
当我们开辟空间后,我们如果需要调整动态内存的大小,那么我们此时可以使用realloc。 当我们要让动态内存变小时,直接在原空间的基础上减小其占用的空间即可; 但是当动态内存要增大扩张时呢?——此时分为两种情况:
  1. 原有空间之后有⾜够⼤的空间
  2. 原有空间之后没有⾜够⼤的空间

如图:

free:

free函数就是用来对“动态内存”进行释放和回收的。

函数原型如下(free - C++ Reference (cplusplus.com)):

  • 如果参数 ptr 指向的空间不是动态开辟的,那free函数的⾏为是未定义的。
  • 如果参数 ptr 是NULL指针,则函数什么事都不做。

注意:free是对“动态”内存进行释放的,而且释放后我们需要将释放的指针置NULL以规避野指针。

3.常见的动态内存的错误

3.1:对NULL指针的解引用操作

如图:

3.2:对动态开辟空间的越界访问

如图:

当运行时程序会报错。

3.3:对非动态开辟的内存使用free函数释放

如图:

此时p指针的空间为固定的,并非动态开辟出的空间,因此不能用free释放,运行时程序会报错。

3.4:使用free释放一块动态开辟内存的一部分

如图:

一如既往的报错。

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

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

4.柔性数组

柔性数组概念比较小众,但它确实存在。

C99中,结构中的最后一个元素允许是未知大小的数组,这就叫柔性数组成员。

如图:

有些编译器不支持a[0]的写法,那么我们改成a[]也是可以的,如图:

柔性数组的特点
  • 结构中的柔性数组成员前⾯必须⾄少有⼀个其他成员。
  • sizeof 返回的这种结构大小不包括柔性数组的内存
  • 包含柔性数组成员的结构用malloc ()函数进⾏内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
例如:
柔性数组的优势

如图:

5.总结C/C++中程序内存区域划分

C/C++程序内存分配的⼏个区域:
  1. 栈区(stack):在执⾏函数时,函数内局部变量的存储单元都可以在栈上创建,函数执⾏结束时 这些存储单元⾃动被释放。栈内存分配运算内置于处理器的指令集中,效率很⾼,但是分配的内 存容量有限。 栈区主要存放运⾏函数⽽分配的局部变量、函数参数、返回数据、返回地址等。
  2. 堆区(heap):⼀般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。分配方式类似于链表。
  3. 数据段(静态区):(static)存放全局变量、静态数据。程序结束后由系统释放。
  4. 代码段:存放函数体(类成员函数和全局函数)的⼆进制代码。


创作不易,如果觉得作者写的勉强能入眼的话给个免费的三连吧亲

标签:malloc,函数,free,内存,动态内存,开辟,调整
From: https://blog.csdn.net/2401_84008419/article/details/139321028

相关文章

  • 重拾信心:一位35岁失业程序员的心理调整之旅
    李明是一名程序员,拥有十多年的工作经验。然而,突如其来的公司裁员让他失去了工作。这一打击让他感到迷茫和无助,仿佛生活的重心瞬间崩塌。最初的几天,李明陷入了深深的自我怀疑和焦虑中。他开始质疑自己的能力,甚至对未来失去了信心。每天早晨醒来,他都感到无所适从,整日无精打采,连......
  • 高德坐标打点(点为正常的WGS84地球坐标系,常见于 GPS 设备,Google 地图等国际标准的坐标
    创建一个js文件工具//WGS84toGCJ-02converter//高德转地球坐标//coordinateUtils.jsconstPI=3.1415926535897932384626;consta=6378245.0;//a:WGS84大地坐标系的长半轴constee=0.00669342162296594323;//ee:WGS84椭球的偏心率平方//WGS84toGC......
  • 【C语言进阶】--- 动态内存管理
    动态内存管理函数1.malloc函数void*malloc(size_tsize);功能:向堆区的空间中申请一块大小为size个字节的空间,返回指向这块空间的指针如果开辟失败会返回一个NULL指针,因此要检查malloc的返回值,避免返回NULL指针后再访问空指针malloc申请的空间,程序退出后会还给操作系统......
  • C语言之动态内存管理
    目录一、什么是动态内存分配二、malloc和free三、calloc和realloc四、常见的动态内存的错误 五、柔性数组六、总结 一、什么是动态内存分配动态内存分配是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。与静态内存分配不同,动态内存分配不需要......
  • 【C语言】动态内存管理
    前言为什么要有动态内存分配?可以回想一下目前为止,我们想要向内存申请一块空间存放数据,有哪些手段呢?目前我们遇到的方式主要有两种:一、创建一个变量。比如我们存放一个整型数据,就创建一个整型变量。(也就是申请4个字节)我们创建一个变量,存放了一个数据。intn=2077;二、如......
  • 深入探索C语言动态内存分配
    在编程的广阔天地里,C语言以其直接操控底层的能力和高效性能,至今仍占据着不可替代的地位。而在C语言的众多特性中,动态内存分配无疑是一项核心而又充满挑战的技术。本文将引领您深入探索这一技术的奥秘,从理论到实践,揭示动态内存分配的魅力所在。一、动态内存分配的必要性在程序......
  • VUE学习笔记(十四)-调整axios拦截器
    调整axios拦截器src/api/api_config.jsimportaxiosfrom"axios";import{getToken}from"@/auth/auth.service";import{ElMessage}from'element-plus'axios.defaults.baseURL="http://localhost:8080/api";axios.defau......
  • 动态内存管理
    目录1.为什么要有动态内存分配2.malloc和free2.1malloc2.2free3.calloc和realloc3.1calloc3.2realloc4.常见的动态内存的错误4.1对NULL指针的解引用操作4.2对动态开辟空间的越界访问4.3对非动态开辟内存使⽤free释放4.4使⽤free释放⼀块动态开辟内存的⼀部......
  • c++动态内存管理干货
     c++兼容c所以之前C语言使用的方式在c++中同样可以使用,但c++给出了更加简便的动态内存管理方法.1.申请内置类型空间c++定义了新的关键字new和delete(都是操作符不是函数),使用方法如图:需要注意的是,用new申请空间默认不会初始化,但是可以初始化。如图:另外,【】里面可以是变量:......
  • Python办公自动化之——调整Word样式(二)
    文档格式自动化是一个非常繁琐但又不可或缺的工作,尤其是在特定场景中,例如每年毕业季的论文排版。在毕业季,学生们需要提交符合严格格式要求的毕业论文,这些要求通常包括封面格式、目录、标题格式、页眉页脚、行间距、段前段后距离、引用格式等。手动调整这些格式不仅耗时,而且容易出......