2. C++ arraynew、malloc和free中的cookie
一. arraynew and deletenew
原理
由图可见,new A[size](size=3)时,构造函数被调用了三次:分别先[0]、后[1]再[2];delete [] A时,析构函数次序逆反也调用了三次:分别先[2]、后[1]再[0]。
注意:如果delete [] A去掉[],会发生内存泄漏,具体见下文。

模拟与结果
#include <iostream>
#include <string>
using namespace std;
class A {
public:
int id;
A() :id(0) {
cout << "default ctor. this=" << this << ", id=" << id << endl;
}
A(int i) :id(i) {
cout << "ctor.this=" << this << ", id=" << id << endl;
}
~A() { cout << "dtor.this=" << this << ", id=" << id << endl; }
};
void test_arraynew() {
size_t size = 3;
A* buf = new A[size];
A* tmp = buf;
cout << "buf=" << buf << " " << "tmp=" << tmp << endl;
for (int i = 0; i < size; ++i)
new (tmp++) A(i); //3次 ctor
cout << "buf=" << buf << " tmp=" << tmp << endl;
delete[] buf; //dtor three times (次序逆反, [2]先於[1]先於[0])
}
int main() {
test_arraynew();
return 0;
}
二. malloc的cookie机制
malloc在为对象分配内存的时候,除了分配指定的内存空间,还会在这段内存空间前后加上两个cookie,其目的是用来记录分配了多少内存,这样在free()的时候我们才能准确的回收内存。所以我们每次调用malloc()分配内存时,都会存在cookie内存消耗。
而new操作符中的array new,为了记录需要调用多少次析构函数,会在分配的内存前记录分配了多少个对象。如下图所示,其中61h是malloc设置的cookie,表示malloc总共分配给用户的内存大小;而00481c30~00481c34这四个字节里存放的3指示分配的对象个数,指示接下来我们应该调用多少次析构函数。

对于这个问题,可以参考这篇博文:https://blog.csdn.net/weixin_29209825/article/details/112070604,里面也有详细的描述。
特殊情况
上面所说的情况只针对有自定义析构函数的情况,如果你定义的类的析构函数是trivially的,即不重要的(编译器默认),那么此时调用delete或者delete[]是不会有什么差别的。因此此时并不会像之前一样用额外的字节数来存储分配对象的个数,因为其析构函数调用或者不调用是没有区别的。

版权声明:本文为ouyangyiwen原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。