关于重载全局new/delete 的一些问题

重载全局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[] 实现原理相关,这里参考:
http://www.cnblogs.com/hazir/p/new_and_delete.html
operator new[] 内部 malloc() 返回的结果是整个memory block,包括了数组大小(32bit 机占4bytes, 64bit机占8bytes)
0x100201f58 - 0x100201f50 = 0x8
new[] 返回的地址是skip 了这个数组大小,指向对象本身。delete[] 也是相同的原理。
3. delete d; 与 delete (void*)d 并不是等价的。
delete d; --> 正常调用析构函数,并释放内存
delete (void*)d; --> 只释放内存,并没有调用析构函数
4. 下面2个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);
具体原因还不明确,以后再补充。

你可能感兴趣的:(C/C++)