C/C++之动态内存申请

本文聚焦C和C++的动态内存申请与释放。开发中需动态申请内存,若不及时释放易致内存泄漏。以字符数组为例,申请内存要考虑字符串结束标志。资源释放方面,系统预定义类型用delete或delete[]均可,自定义类型则需严格匹配new/delete与new[]/delete[],否则会访问非法内存。

前言

在开发中,如果需要在运行时才能确定需要申请的资源类型及内存大小,则需要进行动态内存申请,C提供了mallco/free来进行资源申请,C++还提供了new/delete以及new[]/delete[]来申请资源,手动申请资源需要非常谨慎,如果不及时释放内存,非常容易造成内存泄漏。
今天我们就来研究一下动态内存申请及释放时的坑: 字符数组的长度/资源释放时delete与delete[]的使用

字符数组

 例如在开发中我们需要申请一段内存,来存储size个字符,那么我们应该如何申请内存呢?

我首先想到的是

 char* buf = new char[size];

 这样写似乎没什么问题,但是buf的最后,时不时会出现一些奇怪的字符,谷歌了半天也没搜出来,最后才想到原因,那就是这个动态内存的长度,是有问题的。

 在字符串中,‘\0’被认为是字符串的结束标志,如果一个字符串的最后没有’\0’,那么这个字符串在输出时会出现乱码的问题,并且’\0’是独占一个字节的。

 所以要动态申请内存来存储size个字符,那么就需要申请size+1大小的内存空间,避免字符串末尾出现莫名其妙的乱码。

 char* buf = new char[size+1];

资源释放

1.系统预定义类型

 在上面代码中,我们使用new[]申请了动态内存,当内存使用完后,我们需要手动释放掉这部分内存,那应该使用delete释放还是delete[]来释放呢,这里使用delete或者delete[]都是可以的。
 这是因为char是系统预定义类型,这些类型没有构造函数和析构函数,其他的还有int, float, double等,这些系统预定义类型没有构造函数和析构函数,new只管申请内存,不需要考虑构造和析构,所以即便是使用new[]来申请的内存,只要知道内存大小,delete或者delete[]都可以直接释放内存。

2. 自定义类型

 但是如果不是给预定义类型申请内存,而是给自定义类型申请内存,就需要严格匹配new/delete与new/delete[]了。

 2.1. new[]的机制

 new[]申请自定义类型的内存是,会在返回的内存首地址的前四个字节中保存申请此类型对象的数量,并调用malloc申请指定大小的内存,根据这个数量,new会调用指定数量的构造函数,从而生成对象。

 2.2. delete[]的机制

 delete[]释放内存时,会根据内存地址记录的对象个数调用析构函数,然后再调用free函数释放相应的内存。

 2.3 错误原因:

  如果使用new申请内存,使用delete[]释放内存,delete[]会将地址的前四个字节认为是对象个数,然后调用随机次析构函数,然后内存地址左移四位交给free,free就访问到非法内存,导致出现异常。
  如果使用new[]申请内存,使用delete释放内存,那么delete会直接调用free访问地址,然而地址的前四个字节是对象个数,这就导致free访问了非法内存,程序异常。

 以上就是本文所要分享的内容,希望大家每天坚持进步~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Michael.Scofield

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值