转载

array new 与 array delete

以前在看C++书和上C++课的时候可以看到

delete[] pointer; 

的用法,而大多数对于这个用法没有具体的解释,多是看到:

有一个delete运算符的特殊语法,可以释放动态分配的数组内存:

delete[] p_numbers; 

方括号告诉编译器,指针指向了一个数组,而不是单个值。

引文自: 《C++程序设计:现代方法》 ,14.2 指针和数组

也没有说明如果缺少 [] 会带来的后果,猜想是内存泄露,但是不明就里,于是给我来带了C++内存管理诡谲的印象。不过最近侯捷先生的讲解却很是清晰。

下方所说Complex类为仅包含两个double类型成员,String仅含一个char类型指针。

构造

首先说的是构造,以Complex类为例:

Complex *c = new Complex(1,2); 

执行过程为:

Complex *c; void* mem = operator new( sizeof(Complex) ); //内部调用malloc(n),分配内存 c = static_cast<Complex*>(mem);              //类型转换 c->Complex::Complex(1,2);                    //→Complex::Complex(c,1,2),构造函数 

那么在内存中执行的时候分配内存为:

array new 与 array delete

红色部分为操作系统分配之Cookie,蓝色部分为填充位,目的是为了让整个长度为16的倍数。灰色区域内数据仅在Debug模式下出现,绿色区域为对象所占长度。可计算,Debug模式下的Complex实例长度为:

8[两个双精度浮点实数] + (32+4)[调试模式] + (4×2)[Cookie] → 52 + 12[填充] → 40H 

那么此时向操作系统取内存时Cookie末位置1,即Cookie为 00000041 ,释放时末位置0。之所以保持16(10H)的倍数即如此。

Release下的String类型长度则为:

4[指针] + (4×2)[Cookie] → 12 + 4[填充] → 10H 

释放

执行

String *s = new String(1,2); … delete s; 

delete s 的时候会:

String::~String(s);     //析构函数 operator delete(s);     //释放内存,其内部调用free(s) 

即执行String类析构函数后释放内存,释放Cookie标记段。看起来似乎没什么问题。

数组

看一下

Complex *c = new Complex [3]; 

String *s = new String [3]; 

的内存结构,可以发现是这样的:

array new 与 array delete

在顶部多存储了一个数组长度。那么执行 deletedelete[] 有什么区别呢?是这样的:

array new 与 array delete

可以看到,对于内存而言, delete 一定会将Cookie标记段给释放掉,如果是类似Complex的数组,那么使用 deletedelete[] 的效果是一致的,但是针对String这类含指针类型的数组,使用 delete 仅执行首次析构,也就是在这里出现了内存泄漏。

最近怎么关心内存泄漏了?

程序跑了一晚上泄漏了8G内存,不关心一下怎么得了。

正文到此结束
Loading...