动态内存管理

目录

动态内存函数 

malloc函数

free函数

calloc函数

realloc函数

 几道经典笔试题

题1

 题2

题3

​编辑

题4

柔性数组

柔性数组的特点

柔性数组的优点 


动态内存函数 

malloc函数

动态内存管理_第1张图片

如上图,malloc函数被用来申请10个整形大小的空间,malloc函数的返回类型是void*,因为malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来定义。因此我们需要对他进行强转,然后赋给p即可使用。

malloc函数的返回值: 如果申请的空间开辟成功,则返回一个指向开辟空间的指针。

                                     如果开辟失败,则放回NULL指针,就不能使用了。因此我们需要对返回                                         值进行检查。

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

动态内存管理_第2张图片

我们会习惯性的对malloc的返回值进行检查,如上图,如果返回了NULL,则打印错误的信息。

free函数

free函数是专门用来做动态内存的释放和回收的。

malloc开辟的空间有两个释放方式:

  1. free释放——主动
  2. 程序退出后,malloc申请的空间,也会被系统回收——被动

正常情况下,我们要主动释放。

free函数没有返回值,他的参数就是开辟空间的地址。

动态内存管理_第3张图片

如上图,我们释放时,只是释放了开辟的空间,但p还是指向那个地址,因此,我们会在free之后将该指针变为空指针,否则该指针就是野指针,野指针是危险的。

  • 如果free参数指向的空间不是动态开辟的,则free函数的行为是未定义的。
  • 如果参数是空指针时,则函数什么也不做。

malloc和free都需要引用头文件stdlib.h。

calloc函数

calloc函数和malloc函数返回值类型都一样void*,calloc的参数有两个,参数1指开辟空间的个数,参数2指开辟空间的类型的大小。

如上图,同样开辟10个整形大小的空间,二者的差别不大。除了参数的区别,calloc函数申请好空间后,会将空间初始化为0,但是malloc不初始化。 

realloc函数

  • realloc函数有两个参数,参数1是要调整的空间的地址。
  • 参数2是调整之后的大小。
  • 返回值是调整之后的内存起始地址。
  • 这个函数调整原内存空间的基础上,还会将原来内存中的数据移到新的空间。

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

假设初始已申请10个整形的空间,现需要调整为20个整形的空间。

动态内存管理_第4张图片

  • 原有空间之后有足够的空间

动态内存管理_第5张图片

  • 原有空间之后没有足够大的空间

动态内存管理_第6张图片

如上图,因为后面没有足够大的空间,realloc函数会找一块新的,足够的空间,一次性开辟需要的空间。

  • 旧的空间中的数据,会拷贝到新的空间中。
  • 释放掉旧的空间。
  • realloc函数返回新的空间的地址。 

动态内存管理_第7张图片

realloc也能做malloc能做的事,如果参数1是空指针,上方realloc函数的作用跟注释中malloc函数的作用一样。

 几道经典笔试题

题1

动态内存管理_第8张图片

分析:str指向的空间仍为NULL,因为GetMemory后p会被销毁,程序对str(NULL)进行解引用操作,会使程序崩溃。但是malloc开辟的空间依旧存在,没有释放,会造成内存泄漏。

修改后的代码如下:

动态内存管理_第9张图片

 题2

动态内存管理_第10张图片

分析:p的地址返回给str,但返回时,该空间已经销毁了,即没有了该空间的使用权,str指向了p所指向的地址,但此时str是野指针。

题3

动态内存管理_第11张图片

分析:缺少free,造成内存泄露。

题4

动态内存管理_第12张图片

分析:free后,str指向的空间被释放了,但他依旧指向该地址。strcpy时,此时str为野指针,对野指针进行操作,非法访问内存。 

柔性数组

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

柔性数组的特点

  • 结构体中的柔性数组成员前面必须至少有一个其他成员
  • sizeof返回这种结构大小不包括柔性数组的内存
  • 包含柔性数组成员的结构用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
  • 动态内存管理_第13张图片

如上图,不包括柔性数组的内存。 

柔性数组的优点 

请看下面两组代码

组1:

动态内存管理_第14张图片

动态内存管理_第15张图片 

 组2:

动态内存管理_第16张图片 动态内存管理_第17张图片

 分析组2:组2的结构体中有柔性数组成员,先是申请一块空间,后来空间不够,就realloc进行调整,并把调整后的地址传给先前的ps,开辟的空间是连续的。在释放时,只需要释放一次。

分析组1:组1先是malloc一块空间,然后在data中再malloc一块空间。空间不足时,再realloc调整,然后把新空间的地址传给data。malloc开辟的空间不是连续的。由于malloc了两次,在释放时也需要释放两次,即malloc几次,就要free几次,这样释放内存相较于组1,更为麻烦。如下图。

动态内存管理_第18张图片

组2有两个优点:

  1. 方便内存释放:
  2. 有利于访问速度 

你可能感兴趣的:(c语言笔记,算法)