/// DbgNew.h
#ifndef DEBUGNEW_H
#define DEBUGNEW_H
#include "GameType.h"
#include "GameDefine.h"
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <map>
#include <vector>
using namespace std;
// 内存节点
class MemNode
{
public:
MemNode();
MemNode(X_VOID* Buffer, size_t s, X_CHAR* File, X_INT Line);
MemNode(const MemNode& Temp);
public:
X_VOID* m_pObject; //内存分配后获得的指针
size_t m_nSize; //内存分配的大小
X_CHAR* m_szFileName; //内存分配代码所在文件位置
X_INT m_nLineNum; //内存分配代码所在行号
};
// 统计信息
struct Info
{
X_UINT m_nTotalSize; //分配总大小
X_INT m_nNewCount; //New次数
Info()
{
m_nTotalSize = 0;
m_nNewCount = 0;
}
};
// 内存链
class NewList
{
public:
X_BOOL IsEmpty();
X_VOID Add(const MemNode& Temp);
X_VOID Remove(X_VOID* Object);
X_VOID Check();
protected:
X_VOID __Print(string strInfo);
private:
map<X_VOID*, MemNode> m_NewNodeMap; // New节点
map<string, Info> m_StatisticsMap; // 次数等统计信息
ofstream m_ofs;
};
// typedef
typedef map<X_VOID*, MemNode>::iterator NewNodeMapIter;
typedef map<string, Info>::iterator StatisticsMapIter;
// 重载
extern X_VOID* operator new(size_t Size, X_CHAR* FileName, X_INT LineNum);
extern X_VOID* operator new[](size_t Size, X_CHAR* FileName, X_INT LineNum);
extern X_VOID operator delete(X_VOID* Object);
extern X_VOID operator delete[](X_VOID* Object);
extern X_VOID operator delete(X_VOID* Object, X_CHAR* FileName, X_INT LineNum);
extern X_VOID operator delete[](X_VOID* Object, X_CHAR* FileName, X_INT LineNum);
// 全局变量
extern NewList g_NewList;
#define new new(__FILE__, __LINE__)
#endif
/// DbgNew.cpp
#include "DbgNew.h"
#undef new
#include "XStdio.h"
#include <algorithm>
#include "TimeController.h"
MemNode::MemNode()
{
m_pObject=0;
m_szFileName=0;
}
MemNode::MemNode(X_VOID* Buffer, size_t s, X_CHAR* File, X_INT Line)
{
m_pObject=Buffer;
m_nSize=s;
m_szFileName=File;
m_nLineNum=Line;
}
MemNode::MemNode(const MemNode& Temp)
{
m_szFileName=Temp.m_szFileName;
m_nLineNum=Temp.m_nLineNum;
m_pObject=Temp.m_pObject;
m_nSize=Temp.m_nSize;
}
X_BOOL NewList::IsEmpty()
{
if (m_NewNodeMap.size() > 0)
{
return X_FALSE;
}
else
{
return X_TRUE;
}
}
X_VOID NewList::Add(const MemNode& Temp)
{
m_NewNodeMap.insert(make_pair(Temp.m_pObject, Temp));
}
X_VOID NewList::Remove(X_VOID* pObject)
{
NewNodeMapIter iter = m_NewNodeMap.begin();
NewNodeMapIter endIter = m_NewNodeMap.end();
iter = m_NewNodeMap.find(pObject);
if (iter != endIter)
{
m_NewNodeMap.erase(iter);
}
}
X_VOID NewList::Check()
{
if (!IsEmpty() && TimeController::GetInstance())
{
X_CHAR szFileName[256]={0};
TimeController::GetInstance()->SetThisTime();
XStdio::Snprintf(szFileName, 256, "../log/MemCheck-%d-%d-%d-%d-%d-%d.txt",
TimeController::GetInstance()->GetThisYear(),
TimeController::GetInstance()->GetThisMonth(),
TimeController::GetInstance()->GetThisDay(),
TimeController::GetInstance()->GetThisHour(),
TimeController::GetInstance()->GetThisMinute(),
TimeController::GetInstance()->GetThisSecond());
m_ofs.open(szFileName, ios_base::out);
m_StatisticsMap.clear();
NewNodeMapIter iter, endIter;
StatisticsMapIter iter2, endIter2;
iter = m_NewNodeMap.begin();
endIter = m_NewNodeMap.end();
X_CHAR Line[10] = {0};
for (; iter != endIter; ++iter)
{
// 行号
memset(Line, 0, sizeof(Line));
itoa(iter->second.m_nLineNum, Line, 10);
// 按文件名+行号作为KEY,统计new次数
string key = iter->second.m_szFileName;
key += Line;
iter2 = m_StatisticsMap.find(key);
if (iter2 != m_StatisticsMap.end())
{
iter2->second.m_nNewCount ++;
iter2->second.m_nTotalSize += iter->second.m_nSize;
}
else
{
Info st;
st.m_nNewCount = 1;
st.m_nTotalSize = iter->second.m_nSize;
m_StatisticsMap.insert(make_pair(key, st));
}
}
// 从高到低统计New次数
// sort(m_StatisticsMap.begin(), m_StatisticsMap.end());
iter2 = m_StatisticsMap.begin();
endIter2 = m_StatisticsMap.end();
for (; iter2 != endIter2; iter2++)
{
// 文件名+行号
__Print(iter2->first);
__Print("\t");
// 调用New次数
X_CHAR count[32];
itoa(iter2->second.m_nNewCount, count, 10);
__Print(count);
__Print("\t");
// 总大小
X_CHAR s[64];
itoa(iter2->second.m_nTotalSize, s, 10);
__Print(s);
__Print("\r\n");
}
m_ofs.close();
}
}
X_VOID NewList::__Print(string strInfo)
{
m_ofs.write(strInfo.c_str(),strInfo.length());
m_ofs.flush();
}
NewList g_NewList;
X_VOID* operator new(size_t Size, X_CHAR* FileName, X_INT LineNum)
{
if (Size==(size_t)0) Size=1;
X_VOID* Result=::operator new(Size);
if (!Result) throw bad_alloc();
else
{
MemNode Temp(Result, Size, FileName, LineNum);
g_NewList.Add(Temp);
return Result;
}
}
X_VOID* operator new[](size_t Size, X_CHAR* FileName, X_INT LineNum)
{
if (Size==(size_t)0) Size=1;
X_VOID* Result=::operator new[](Size);
if (!Result) throw bad_alloc();
else
{
MemNode Temp(Result, Size, FileName, LineNum);
g_NewList.Add(Temp);
return Result;
}
}
X_VOID operator delete(X_VOID* Object)
{
if (!Object) return;
g_NewList.Remove(Object);
free(Object);
}
X_VOID operator delete[](X_VOID* Object)
{
if (!Object) return;
g_NewList.Remove(Object);
free(Object);
}
X_VOID operator delete(X_VOID* Object, X_CHAR* FileName, X_INT LineNum)
{
if (!Object) return;
g_NewList.Remove(Object);
free(Object);
}
X_VOID operator delete[](X_VOID* Object, X_CHAR* FileName, X_INT LineNum)
{
if (!Object) return;
g_NewList.Remove(Object);
free(Object);
}