API 阅读(37) 评论(0)
   时间总是能让一切改变,至上次发blog我已经不在福州。现在就职于成都一家公司,刚来一直在阅读代码,发现服务器的逻辑代码,有挺多让直接new申请内存,对这个我总觉得有些裸奔的感觉。啊哈,有可能被同事看到,我没有其他意思哈,只是觉得没有管理,一不小心就内存泄露了,写的时候要小心又小心。如果要从堆中获取一块内存,一般还是交给智能指针去管理更妥些。
    以上这大段和下面写的都没有任何关系。嗯,是的,确实是没有关系,我只是在思考已经这样写了,能不能对内存申请和释放做个监控。其实网上代码一堆,我也自己按照自己的思路实现了一下,原理都是重载new和delete方式了。闲言少叙,话不多说。
   同样,我也要重载new与delete关键字,但是我重载的是带3参数的,具体的申请交给我的CMemLeakMonitorMgr管理器吧。以后再具体说明,先看如下代码:

voidoperator new(size_t size, const char* funName, size_t line)
{
    return g_pMemLeakMonitorMgr.Alloc(funName,line,size);
}
voidoperator new[](size_t size, const char* file, int line)
{
    return operator new(size, file, line);
}

voidoperator new(size_t size)
{
    return malloc(size);
}
voidoperator new[](size_t size)
{
    return malloc(size);
}

voidoperator new(size_t size, const std::nothrow_t&) throw()
{
    return ::operator new(size);
}
voidoperator new[](size_t size, const std::nothrow_t&) throw()
{
    return ::operator new[](size);
}

void  operator delete(void* p)
{
    return g_pMemLeakMonitorMgr.Free(p);
}
   然后我定义以下宏,来替换new操作,请看下面:

#define DEBUG
#ifdef DEBUG
#define DEBUG_NEW new(__FUNCTION__, __LINE__)
#define DEBUG_DELETE(p) delete p
#else
#define DEBUG_NEW new
#define DEBUG_DELETE(p) delete p
#endif

上面的宏应该不用多说吧,设计的是只有在debug情况下,才会生效。这里用DEBUG_NEW与DEBUG_DELETE宏来申请和释放内存,其实完全可以直接替换new与delete,但是我不想这么做,因为我想在使用者用该宏时明白它做了一些“见不得人”的事情。哈,是那句话闲言少叙,废话不能多。看下怎么使用吧:

void fun1()
{
    DEBUG_NEW int;
}

void fun2()
{
    char *p = DEBUG_NEW char;
    DEBUG_DELETE(p);
}


void fun3()
{
    DEBUG_NEW int;
}


int main()
{
    Test2 *p = DEBUG_NEW Test2();
    DEBUG_DELETE(p);

    fun1();
    fun2();
    fun3();
    fun1();
    fun1();

    g_pMemLeakMonitorMgr.ReportMemLeak();
    return 0;
}
嗯,是的,这个很好懂,通过宏来替换之前的new和delete,然后几个函数中有些函数是有内存泄露的。然后通过ReportMemLeak来报告结果。可以显示的如下:

Test2 constructor.
Test2 destructor.
Test2 constructor.
Test2 destructor.
Memory leak FunName:fun1,line:182,totalsize:12 bytes.
Memory leak FunName:fun3,line:194,totalsize:4 bytes.