#ifndef _DEBUG_NEW_H_
#define _DEBUG_NEW_H_
#include <list>
using namespace std;
typedef struct tagALLOC_ADDR_INFO
{
void * pAddress;
unsigned long nSize;
char szFileName[64];
unsigned long nFileLine;
}
ALLOC_ADDR_INFO, *PALLOC_ADDR_INFO;
static list<ALLOC_ADDR_INFO> AllocList;
//-------------------------------------------------------------------------
void AddressInfo_Add (void *_pAddr, unsigned long _nSize, const char *_szName, unsigned long _nLine);
void AddressInfo_Del (void *_pAddr);
void AddressInfo_Dump ();
void * __cdecl operator new (size_t _Size, const char *_szFile, unsigned long _nLine);
void * __cdecl operator new[] (size_t _Size, const char *_szFile, unsigned long _nLine);
void __cdecl operator delete (void *_pPtr);
void __cdecl operator delete[] (void *_pPtr);
#define DEBUG_NEW new(__FILE__, __LINE__)
#define new DEBUG_NEW
//-------------------------------------------------------------------------
#endif
Обнаружение Утечки Памяти
Перейду сразу к делу.. Писал свой очередной проектик, столкнулся с проблемой утечки памяти. Начав поиски по отлавливанию подобного явления быстро наткнулся на статью "Как обнаружить утечку памяти"
После прочтения, приступил к реализации:
Код:
Код:
#include "Debug.h"
#include <windows.h>
//-------------------------------------------------------------------------
void AddressInfo_Add(void *_pAddr, unsigned long _nSize, const char *_szName, unsigned long _nLine)
{
ALLOC_ADDR_INFO info;
info.pAddress = _pAddr;
info.nSize = _nSize;
info.nFileLine = _nLine;
strncpy_s(info.szFileName, 63, _szName, 63);
AllocList.insert(AllocList.begin(), info);
};
//-------------------------------------------------------------------------
void AddressInfo_Del(void *_pAddr)
{
list<ALLOC_ADDR_INFO>::iterator it;
for(it = AllocList.begin(); it != AllocList.end(); it++)
{
if(it->pAddress == _pAddr)
{
AllocList.erase(it);
break;
}
}
};
//-------------------------------------------------------------------------
void AddressInfo_Dump()
{
list<ALLOC_ADDR_INFO>::iterator it;
unsigned long nTotalSize = 0;
char szBuf[1024];
sprintf_s(szBuf, sizeof(szBuf), "[BEGIN]-------------------------------------------");
OutputDebugStringA(szBuf);
for(it = AllocList.begin(); it != AllocList.end(); it++)
{
sprintf_s(szBuf, sizeof(szBuf), "%s:\tLINE %d,tADDRESS %.4X [%d] Unfreed!",
it->szFileName, it->nFileLine, (unsigned long)it->pAddress, it->nSize);
nTotalSize += it->nSize;
OutputDebugStringA(szBuf);
}
sprintf_s(szBuf, sizeof(szBuf), "--------------------------------------------------");
OutputDebugStringA(szBuf);
sprintf_s(szBuf, sizeof(szBuf), "Total Unfreed: %d bytes", nTotalSize);
OutputDebugStringA(szBuf);
};
//-------------------------------------------------------------------------
void * __cdecl operator new(size_t _Size, const char *_szFile, unsigned long _nLine)
{
void *pPtr;
if((pPtr = malloc(_Size)) != NULL)
{
AddressInfo_Add(pPtr, _Size, _szFile, _nLine);
}
else
{
throw std::bad_alloc();
}
return pPtr;
};
//-------------------------------------------------------------------------
void * __cdecl operator new[](size_t _Size, const char *_szFile, unsigned long _nLine)
{
void *pPtr;
if((pPtr = malloc(_Size)) != NULL)
{
AddressInfo_Add(pPtr, _Size, _szFile, _nLine);
}
else
{
throw std::bad_alloc();
}
return pPtr;
};
//-------------------------------------------------------------------------
void __cdecl operator delete(void *_pPtr)
{
AddressInfo_Del(_pPtr);
free(_pPtr);
};
//-------------------------------------------------------------------------
void __cdecl operator delete[](void *_pPtr)
{
AddressInfo_Del(_pPtr);
free(_pPtr);
};
//-------------------------------------------------------------------------
#include <windows.h>
//-------------------------------------------------------------------------
void AddressInfo_Add(void *_pAddr, unsigned long _nSize, const char *_szName, unsigned long _nLine)
{
ALLOC_ADDR_INFO info;
info.pAddress = _pAddr;
info.nSize = _nSize;
info.nFileLine = _nLine;
strncpy_s(info.szFileName, 63, _szName, 63);
AllocList.insert(AllocList.begin(), info);
};
//-------------------------------------------------------------------------
void AddressInfo_Del(void *_pAddr)
{
list<ALLOC_ADDR_INFO>::iterator it;
for(it = AllocList.begin(); it != AllocList.end(); it++)
{
if(it->pAddress == _pAddr)
{
AllocList.erase(it);
break;
}
}
};
//-------------------------------------------------------------------------
void AddressInfo_Dump()
{
list<ALLOC_ADDR_INFO>::iterator it;
unsigned long nTotalSize = 0;
char szBuf[1024];
sprintf_s(szBuf, sizeof(szBuf), "[BEGIN]-------------------------------------------");
OutputDebugStringA(szBuf);
for(it = AllocList.begin(); it != AllocList.end(); it++)
{
sprintf_s(szBuf, sizeof(szBuf), "%s:\tLINE %d,tADDRESS %.4X [%d] Unfreed!",
it->szFileName, it->nFileLine, (unsigned long)it->pAddress, it->nSize);
nTotalSize += it->nSize;
OutputDebugStringA(szBuf);
}
sprintf_s(szBuf, sizeof(szBuf), "--------------------------------------------------");
OutputDebugStringA(szBuf);
sprintf_s(szBuf, sizeof(szBuf), "Total Unfreed: %d bytes", nTotalSize);
OutputDebugStringA(szBuf);
};
//-------------------------------------------------------------------------
void * __cdecl operator new(size_t _Size, const char *_szFile, unsigned long _nLine)
{
void *pPtr;
if((pPtr = malloc(_Size)) != NULL)
{
AddressInfo_Add(pPtr, _Size, _szFile, _nLine);
}
else
{
throw std::bad_alloc();
}
return pPtr;
};
//-------------------------------------------------------------------------
void * __cdecl operator new[](size_t _Size, const char *_szFile, unsigned long _nLine)
{
void *pPtr;
if((pPtr = malloc(_Size)) != NULL)
{
AddressInfo_Add(pPtr, _Size, _szFile, _nLine);
}
else
{
throw std::bad_alloc();
}
return pPtr;
};
//-------------------------------------------------------------------------
void __cdecl operator delete(void *_pPtr)
{
AddressInfo_Del(_pPtr);
free(_pPtr);
};
//-------------------------------------------------------------------------
void __cdecl operator delete[](void *_pPtr)
{
AddressInfo_Del(_pPtr);
free(_pPtr);
};
//-------------------------------------------------------------------------
Собственно никаких существенных отличий от кода приведенного в статье нет (хотя в статье допущенны очевидные ошибки, автор сам наверно не пробовал даже это реализовать :). Но вот оператор new перегружается как то коряво и соответсвенно не работоспособно. Просматривал сорцы CRT (new.h), но в этой каше define'ов ничего не понятно.. Прошу помочь с решением данной проблемы.. все таки вещь очень полезная.. если конечно реализуемая, т.к. не понятно как вызывать конструктор деструктор для объектов.. хотя вроде для каждого класса нужно свои операторы new/delete перегружать... тогда получается нельзя создать "глобально перегруженный"?! :)
Если ты пишешь под Visual Studio, то там есть стандартные средства ловли memory leak'ов. Только если я не ошибаюсь - они доступны в тим едишн. И код для этого модифицировать не нада. Не знаю, или в более ранних версиях была эта фича или нет, но в 2005 студии, точно есть. Code Analysis называется.
Да пишу конечно под студией (уже под 2008 Team Suite), баги то свои я закрыл дело не в них. Просто интересно было саму идею реализовать.. Да и малоли, вдруг понадобиться писать свою систему распределения памяти и придется оператор new перегружать :)
Во-первых, в 2005 студии неплохо сделан контроль на всякие баги, типа использования не инициализированной переменной, деления на ноль...
Во-вторых сдинамической памятью работаю только через STL или boost. Нужен массив - vector в помощь, указатель на память - полно всяких указателей, и умных и гениальных.
Ну а если уж совсем глухо то можно юзать специальные пакеты для отлова утечек. Работал с линейкой Rational, еще в 6й студии - очень помогла при отлове чужих ошибок, где можно было встретить двойной delete :)