前言
在开发中,如果需要在运行时才能确定需要申请的资源类型及内存大小,则需要进行动态内存申请,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访问了非法内存,程序异常。
以上就是本文所要分享的内容,希望大家每天坚持进步~
本文聚焦C和C++的动态内存申请与释放。开发中需动态申请内存,若不及时释放易致内存泄漏。以字符数组为例,申请内存要考虑字符串结束标志。资源释放方面,系统预定义类型用delete或delete[]均可,自定义类型则需严格匹配new/delete与new[]/delete[],否则会访问非法内存。

1358

被折叠的 条评论
为什么被折叠?



