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

 重点学习内容

动态内存管理四大函数

 Malloc 内存申请函数

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

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

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

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

搭配free使用的方式:

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

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

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

calloc 开辟空间并初始化函数

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

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

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

realloc 动态内存调整函数

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

内存调整的两种情况:

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

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

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

代码实现扩容的正确方式

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

realloc当做malloc使用的方式:

内存池概念:

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

常见的动态内存错误

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

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

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

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

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

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

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

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

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

 

实例:

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

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

 举例:

 柔型数组的特点

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

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

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

 

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

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

补充:变长数组概念

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值