c语言进阶-动态内存管理

 重点学习内容

c语言进阶-动态内存管理_第1张图片

动态内存管理四大函数

c语言进阶-动态内存管理_第2张图片

 Malloc 内存申请函数

返回值是无类型的指针,指向分配的内存的首地址。申请失败会返回空指针。

c语言进阶-动态内存管理_第3张图片

malloc返回值是void*类型,使用时需要强制转换成所需类型。

malloc和free匹配使用,但是如果不free释放内存,内存也会在程序运行结束后自动释放。

但是程序如果是不停止的运行的话,则最好使用free搭配来释放内存。

搭配free使用的方式:

c语言进阶-动态内存管理_第4张图片

 释放空间使用free(p);p=null;

因为p指针释放内存后,所指向空间使用权交还给系统,但是原来p指针变量内存储的指向的空间的地址还存在p当中,此时p解引用还是可以访问所指向空间,成为野指针。所以最好在free后给p赋空值。

c语言进阶-动态内存管理_第5张图片

free释放的内存必须是动态内存分配的内存。

c语言进阶-动态内存管理_第6张图片

calloc 开辟空间并初始化函数

按照元素个数和大小开辟空间。返回值也是void*  指向开辟好的空间的起始地址。

返回之前会提前把开辟的空间初始化位0,然后再返回。

malloc和calloc的区别就是返回之前是否有初始化开辟的空间。

c语言进阶-动态内存管理_第7张图片

realloc 动态内存调整函数

当动态分配的内存不够或者过多时,用此函数调整。

c语言进阶-动态内存管理_第8张图片

c语言进阶-动态内存管理_第9张图片

内存调整的两种情况:

c语言进阶-动态内存管理_第10张图片

 当追加的连续字节已被占用,则此函数会在堆中找空闲内存,重新分配所需的内存,把原分配内存的内容拷贝到新地址,然后返回新的地址。旧空间不用手动释放,会自动释放。

c语言进阶-动态内存管理_第11张图片

直接在后面追加内存,并由原地址继续管理。

频繁的malloc会带来效率的下降,因为开辟的空间之间会产生内存碎片,内存碎片未被利用就会浪费,内存利用率下降。并且每一次开辟和释放都需要消耗系统资源。

代码实现扩容的正确方式

c语言进阶-动态内存管理_第12张图片

为了防止扩容失败后空指针覆盖原指针,所以用新的指针接收realloc的返回值, 并判断是否是空指针,在进行赋值。

realloc当做malloc使用的方式:

c语言进阶-动态内存管理_第13张图片

内存池概念:

一次性申请一块相对较大的空间,程序自己来维护和使用。

常见的动态内存错误

c语言进阶-动态内存管理_第14张图片

 避免空指针解引用的解决办法

 使用内存开辟函数,一定需要对返回值进行检测是否为空指针。

c语言进阶-动态内存管理_第15张图片

对非动态开辟空间进行free也是错误的

c语言进阶-动态内存管理_第16张图片

使用free释放一块动态开辟内存的一部分也是错误的

使用free释放动态内存开辟的空间,必须是开辟的空间的首地址,如果一旦指向首地址的指针变量发生变化,free则会编译报错。

c语言进阶-动态内存管理_第17张图片

对同一块动态开辟的内存进行多次释放也是错误的

解决方法可以是在第一次free后,把p指针赋为空指针,避免成为野指针和二次释放报错。

c语言进阶-动态内存管理_第18张图片

动态开辟内存后,没有释放内存,产生内存泄露风险。

不用又不释放则会内存泄露。

c语言进阶-动态内存管理_第19张图片

 c语言进阶-动态内存管理_第20张图片

实例:

c语言进阶-动态内存管理_第21张图片

 函数内创建的形参,函数结束后会释放。str仍是空指针。

柔性数组(一个重点技巧)

c语言进阶-动态内存管理_第22张图片

 举例:

c语言进阶-动态内存管理_第23张图片

 柔型数组的特点

c语言进阶-动态内存管理_第24张图片

 包含柔性数组的结构体,创建变量时不能直接创建,直接创建会忽略掉柔型数组成员。

创建方法含柔性数组的结构体变量 的方法: 

c语言进阶-动态内存管理_第25张图片

两次malloc手动实现柔型数组的实例:

c语言进阶-动态内存管理_第26张图片

 

直接创建柔性数组的优势:

c语言进阶-动态内存管理_第27张图片

柔性数组可以解决在堆中创建带数组的结构体需要两次malloc的问题。减少开辟次数,产生较少内存碎片,提高访问速度。

补充:变长数组概念

变长数组是在c99标准才支持边长数组,并且边长数组并不意味着长度可变,而是数组长度支持使用变量来表示。

c语言进阶-动态内存管理_第28张图片

你可能感兴趣的:(c语言,开发语言)