2. C++ arraynew、malloc和free中的cookie

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版权协议,转载请附上原文出处链接和本声明。