C++内存泄漏处理

/*
功能: 我们重载了operator new是全局的,new运算符先调用我们重载的operator new,再调用相应的构造函数,
一般来讲都是使用placement new直接在operator new返回的指针上调用相应的构造函数。
这里如果我们重载的是类的operator new会优先调用类内的,而不是全局的,即使类内的调用错误也不会向外找了。
*/
【memchecker.h】
struct MemIns
{
    void* pMem;
    int m_nSize;
    char m_szFileName[256];
    int m_nLine;
    MemIns* pNext;
};
class MemManager
{
public:
    MemManager();
    ~MemManager();
private:
    MemIns *m_pMemInsHead;
    int m_nTotal;
public:
    static MemManager* GetInstance();
    void Append(MemIns *pMemIns);
    void Remove(void *ptr);
    void Dump(); 
};
void* operator new(size_t size, const char* szFile, int nLine);
void operator delete(void* ptr, const char* szFile, int nLine);
void operator delete(void* ptr);
void* operator new[] (size_t size, const char* szFile, int nLine);
void operator delete[](void* ptr, const char* szFile, int nLine);
void operator delete[](void* ptr);


【memchecker.cpp】
#include"memchecker.h"
#include<stdio.h>
#include <stdlib.h>
#include<malloc.h>
#include<string.h>

MemManager::MemManager()
{
    m_pMemInsHead=NULL;
    m_nTotal=NULL;
}

MemManager::~MemManager()
{

}

void MemManager::Append(MemIns* pMemIns)
{
   pMemIns->pNext=m_pMemInsHead;
    m_pMemInsHead = pMemIns;
   m_nTotal+= m_pMemInsHead->m_nSize;
}

void MemManager::Remove(void* ptr)
{
    MemIns* pCur = m_pMemInsHead;
    MemIns* pPrev = NULL;
    while(pCur)
    {
        if(pCur->pMem == ptr)
        {
            if(pPrev)
            {
                pPrev->pNext = pCur->pNext;
            }
            else
            {
                m_pMemInsHead = pCur->pNext;
            }
            m_nTotal -= pCur->m_nSize;
            free(pCur);
            break;
        }
        pPrev = pCur;
        pCur = pCur->pNext;
    }
}

void MemManager::Dump()
{
    MemIns* pp = m_pMemInsHead;
    while(pp)
    {
        printf( "File is %s\n", pp->m_szFileName );
        printf( "Size is %d\n", pp->m_nSize );
        printf( "Line is %d\n\n", pp->m_nLine );
        pp = pp->pNext;
    }
}

void PutEntry(void *ptr, int size, const char* szFile, int nLine)
{
    MemIns* p = (MemIns*)(malloc(sizeof(MemIns)));
    if(p)
    {
        strcpy(p->m_szFileName, szFile);
        p->m_nLine = nLine;
        p->pMem = ptr;
        p->m_nSize = size;
        MemManager::GetInstance()->Append(p);
    }
}

void RemoveEntry(void* ptr)
{
    MemManager::GetInstance()->Remove(ptr);
}

void* operator new(size_t size, const char* szFile, int nLine)
{
    void* ptr = malloc(size);
    PutEntry(ptr, size, szFile, nLine);
    return ptr;
}

void operator delete(void *ptr)
{
    RemoveEntry(ptr);
    free(ptr);
}

void operator delete(void* ptr, const char* file, int line)
{
    RemoveEntry(ptr);
    free(ptr);
}

void* operator new[](size_t size, const char* szFile, int nLine)
{
    void * ptr = malloc(size);
    PutEntry(ptr, size, szFile, nLine);
    return ptr;
}

void operator delete[](void *ptr)
{
    RemoveEntry(ptr);
    free(ptr);
}

void operator delete[](void* ptr ,const char* szFile, int nLine)
{
    RemoveEntry(ptr);
    free(ptr);
}

/*
重载new思想:
operator new的重载是可以有自定义参数的,那么我们如何利用自定义参数获取更多的信息呢,这里一个很有用的做法
就是给operator new添加两个参数:char* file, int line,这两个参数记录new运算符的位置,然后再在new时
将文件名和行号传入,这样我们就能在分配内存失败时给出提示:输出文件名和行号。
那么如何获取当前语句所在文件名和行号呢,windows提供两个宏:__FILE__和__LINE__。
利用它们可以直接获取到文件名和行号,也就是 new(__FILE__, __LINE__) 由于这些都是不变的,
因此可以再定义一个宏:#define new new(__FILE__, __LINE__)。这样我们就只需要定义这个宏,
然后重载operator new即可。
*/

#define new new(__FILE__,__LINE__)
MemManager m_memTracer;

MemManager* MemManager::GetInstance()
{
   return &m_memTracer;
} 

int main()
{
    int *plen =new int ;
    *plen=10;
    //delete plen;          //注意这两次delete走的都是delete重载void*参数的,没有走参数多的那项
    char *pstr=new char[35];
    strcpy(pstr,"hello memory leak");
    //delete[] pstr;        //同上
    m_memTracer.Dump();
    system("pause");
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值