动态内存管理

简介: 动态内存管理

动态内存函数

# malloc函数

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

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

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

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

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

# free函数

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

malloc开辟的空间有两个释放方式:
1.free释放——主动
2.程序退出后,malloc申请的空间,也会被系统回收——被动
正常情况下,我们要主动释放。

free函数没有返回值,他的参数就是开辟空间的地址。
image.png
如上图,我们释放时,只是释放了开辟的空间,但p还是指向那个地址,因此,我们会在free之后将该指针变为空指针,否则该指针就是野指针,野指针是危险的。

  • 如果free参数指向的空间不是动态开辟的,则free函数的行为是未定义的。
  • 如果参数是空指针时,则函数什么也不做。
    malloc和free都需要引用头文件stdlib.h。

    # calloc函数

    calloc函数和malloc函数返回值类型都一样void*,calloc的参数有两个,参数1指开辟空间的个数,参数2指开辟空间的类型的大小。
    image.png
    如上图,同样开辟10个整形大小的空间,二者的差别不大。除了参数的区别,calloc函数申请好空间后,会将空间初始化为0,但是malloc不初始化。

    # realloc函数

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

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

  • 原有空间之后有足够的空间
    image.png
  • 原有空间之后没有足够大的空间
    image.png
    如上图,因为后面没有足够大的空间,realloc函数会找一块新的,足够的空间,一次性开辟需要的空间。
  • 旧的空间中的数据,会拷贝到新的空间中。
  • 释放掉旧的空间。
  • realloc函数返回新的空间的地址。
    image.png
    realloc也能做malloc能做的事,如果参数1是空指针,上方realloc函数的作用跟注释中malloc函数的作用一样。

    几道经典笔试题

    # 题1

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

修改后的代码如下:
image.png

# 题2

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

# 题3

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

# 题4

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

柔性数组

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

# 柔性数组的特点

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

    # 柔性数组的优点

    请看下面两组代码

    # # 组1:

    image.png
    image.png

    # # 组2:

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

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

目录
相关文章
|
6月前
|
编译器
【动态内存管理】
【动态内存管理】
35 0
|
1月前
|
编译器 程序员 C语言
动态内存管理(超详细!)
动态内存管理(超详细!)
26 2
|
1月前
|
程序员 C语言 C++
详解动态内存管理!
详解动态内存管理!
|
3月前
|
C++
动态内存管理
动态内存管理
33 0
|
4月前
|
程序员 编译器 C语言
动态内存管理总结
动态内存管理总结
37 0
|
4月前
|
程序员 C语言 C++
动态内存管理-2
动态内存管理
20 0
|
4月前
|
程序员 编译器
动态内存管理-1
动态内存管理
32 0
|
5月前
|
C语言 C++
C++中的动态内存管理
C++中的动态内存管理
|
5月前
|
程序员 编译器 C语言
动态内存管理(上)
动态内存管理(上)
26 0
|
7月前
|
编译器 C++
动态内存管理详解
动态内存管理详解