重载全局new/delete的做法,网上已经可以搜到很多,不再赘述。
class A
{
public:
A() { printf("%s, %d\n", __func__, __LINE__); }
~A() { printf("%s, %d\n", __func__, __LINE__); }
};
void* operator new(size_t size, const char* file, int line)
{
void* ptr = malloc(size);
printf("new -> %p\n", ptr);
return ptr;
}
void* operator new[](size_t size, const char* file, int line)
{
void* ptr = malloc(size);
printf("new[] -> %p\n", ptr);
return ptr;
}
void operator delete(void* ptr, const char* file, int line)
{
printf("delete -> %p\n", ptr);
free(ptr);
}
void operator delete[](void* ptr, const char* file, int line)
{
printf("delete[] -> %p\n", ptr);
free(ptr);
}
void operator delete(void* ptr)
{
printf("delete2 -> %p\n", ptr);
free(ptr);
}
void operator delete[](void* ptr)
{
printf("delete2[] -> %p\n", ptr);
free(ptr);
}
#define new new(__FILE__, __LINE__)
//#define YYDelete delete
int main(int argc, const char * argv[])
{
A* a = new A();
printf("a -> %p\n", a);
delete a;
char* b = new char[100];
printf("b -> %p\n", b);
delete[] b;
A* c = new A[2];
printf("c -> %p\n", c);
delete[] c;
A* d = new A();
delete (void*)a;
return 0;
}
运行结果:
new -> 0x100400020
A, 26
a -> 0x100400020
~A, 27
delete2 -> 0x100400020
new[] -> 0x1003057d0
b -> 0x1003057d0
delete2[] -> 0x1003057d0
new[] -> 0x100201f50
A, 26
A, 26
c -> 0x100201f58
~A, 27
~A, 27
delete2[] -> 0x100201f50
new -> 0x100300ac0
A, 26
delete2 -> 0x100300ac0
从结果来看,能看出几个问题:1. 对于基本数据类型, 如 char/short/int 等,operator new[] 内部 malloc() 结果与new 返回值是一致的。
new[] -> 0x1003057d0
b -> 0x1003057d0
delete2[] -> 0x1003057d0
2. 对于非基本数据类型,如class,operator new[] 内部 malloc() 结果与new 返回值是不一致的。
new[] -> 0x100201f50
A, 26
A, 26
c -> 0x100201f58
~A, 27
~A, 27
delete2[] -> 0x100201f50
至于这个差异,应该是由于new[], delete[] 实现原理相关,这里参考:
0x100201f58 - 0x100201f50 = 0x8
new[] 返回的地址是skip 了这个数组大小,指向对象本身。delete[] 也是相同的原理。
void operator delete(void* ptr, const char* file, int line);
void operator delete[](void* ptr, const char* file, int line);
默认只进入:
void operator delete(void* ptr);
void operator delete[](void* ptr);
具体原因还不明确,以后再补充。