PoEdu培训 C++项目班 第六课 内存泄露检测
文章类别: 培训笔记 0 评论

PoEdu培训 C++项目班 第六课 内存泄露检测

文章类别: 培训笔记 0 评论

内存泄露检测

指针异常

内存泄露的检测

在每个头文件中加入 #include "DebugNew.h 头文件即可, 仅在DEBUG下有效.
代码如下:

// TracerNew.h
#ifndef _TRACER_NEW_H_
#define _TRACER_NEW_H_

#ifndef NDEBUG

#include <map>

// 全局重载new
void* operator new (size_t nSize, const char* szFile, long lLine);
// 全局重载delete
void operator delete(void* p);

class TracerNew
{
    class TracerNewInfo
    {
    public:
        TracerNewInfo(const char* szFile = nullptr, long lLine = 0);
        const char* File() const;
        long Line() const;
    private:
        const char* szFile_;
        long lLine_;
    };

    class Lock
    {
    public:
        Lock(TracerNew& tracer) : tracer_(tracer)
        {
            ++tracer_.lLockCount_;
        }
        ~Lock()
        {
            --tracer_.lLockCount_;
        }
    private:
        TracerNew& tracer_;
    };
public:
    TracerNew();
    ~TracerNew();

    void Add(void* p, const char* szFile, long lLine);
    void Remove(void* p);
    void Dump();

    static bool Ready;

private:
    std::map<void*, TracerNewInfo> tracerInfos_;
    long lLockCount_;
};

extern TracerNew newTracer;

#endif // !NDEBUG

#endif // !_TRACER_NEW_H_

// TracerNew.cpp
#include "TracerNew.h"

#ifndef NDEBUG

#include <cstdlib>
#include <iostream>

TracerNew newTracer;
bool TracerNew::Ready = false;

void* operator new(size_t nSize, const char * szFile, long lLine)
{
    void* p = malloc(nSize);
    // 开始记录
    if (TracerNew::Ready)
        newTracer.Add(p, szFile, lLine);
    return p;
}

void operator delete(void * p)
{
    if (TracerNew::Ready)
        newTracer.Remove(p);
    free(p);
}

TracerNew::TracerNew() : lLockCount_(0)
{
    TracerNew::Ready = true;
}


TracerNew::~TracerNew()
{
    TracerNew::Ready = false;
    Dump();
}

void TracerNew::Add(void* p, const char * szFile, long lLine)
{
    if (lLockCount_ > 0)
        return;
    //++lLockCount_;
    Lock l(*this);
    tracerInfos_[p] = TracerNewInfo(szFile, lLine);
    //--lLockCount_;
}

void TracerNew::Remove(void * p)
{
    if (lLockCount_ > 0)
        return;
    //++lLockCount_;
    Lock l(*this);
    auto iter = tracerInfos_.find(p);
    if (iter != tracerInfos_.end())
    {
        // 找到了
        tracerInfos_.erase(p);
    }
    //--lLockCount_;
}

void TracerNew::Dump()
{
    for each (auto tracerInfo in tracerInfos_)
    {
        std::cout << "0x" << tracerInfo.first << ":\t" 
            << tracerInfo.second.File() << "\t In Line:" 
            << tracerInfo.second.Line() << std::endl;
    }
}

TracerNew::TracerNewInfo::TracerNewInfo(const char * szFile, long lLine)
    : szFile_(szFile), lLine_(lLine)
{
}

const char* TracerNew::TracerNewInfo::File() const
{
    return szFile_;
}

long TracerNew::TracerNewInfo::Line() const
{
    return lLine_;
}

#endif // !NDEBUG

// DebugNew.h
#ifndef _DEBUG_NEW_H_
#define _DEBUG_NEW_H_

#ifndef NDEBUG

#include "TracerNew.h"

#define new new(__FILE__, __LINE__)

#endif // !NDEBUG

#endif // !_DEBUG_NEW_H_

如有错误,请提出指正!谢谢.

回复