Windows 程序内存泄漏检测是一项十分重要的工作,基于 GUI 的应用程序通常在调试结束时也有内存泄漏报告,但这个报告的信息不全面,不能定位到产生泄漏的具体行号。其实自己实现一个内存泄漏检测工具是一件非常简单的事情,但看过网上写的很多例子,普遍存在两种问题:
struct _CrtMemState;
_CrtSetDbgFlag();
_CrtMemCheckpoint();
_CrtMemCheckpoint();
_CrtMemDifference();
_CrtMemDumpStatistics();
_malloc_dbg();
_free_dbg();
#pragma once
#if defined _DEBUG && defined _DETECT_MEMORY_LEAK
#ifdef new
#undef new
#endif
#ifdef delete
#undef delete
#endif
#ifndef _CRTDBG_MAP_ALLOC
#define _CRTDBG_MAP_ALLOC
#endif
#include <crtdbg.h>
namespace __dbg_impl
{
class CDebugEnv
{
public:
CDebugEnv()
{
::_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
::_CrtMemCheckpoint(&s1);
}
~CDebugEnv()
{
::_CrtMemCheckpoint(&s2);
if (::_CrtMemDifference( &s3, &s1, &s2))
{
TRACE0("!! Memory stats !!\n");
TRACE0("----------------------------------------\n");
::_CrtMemDumpStatistics(&s3);
TRACE0("----------------------------------------\n");
}
}
private:
_CrtMemState s1, s2, s3;
};
static __dbg_impl::CDebugEnv __dbgEnv;
}
inline void* __cdecl operator new(size_t nSize, const char* lpszFileName, int nLine)
{
return ::_malloc_dbg(nSize, _NORMAL_BLOCK, lpszFileName, nLine);
}
inline void* __cdecl operator new[](size_t nSize, const char* lpszFileName, int nLine)
{
return operator new(nSize, lpszFileName, nLine);
}
inline void* __cdecl operator new(size_t nSize)
{
return operator new(nSize, __FILE__, __LINE__);
}
inline void* __cdecl operator new[](size_t nSize)
{
return operator new(nSize, __FILE__, __LINE__);
}
inline void* __cdecl operator new(size_t nSize, const std::nothrow_t&)
{
return operator new(nSize, __FILE__, __LINE__);
}
inline void* __cdecl operator new[](size_t nSize, const std::nothrow_t&)
{
return operator new(nSize, __FILE__, __LINE__);
}
inline void __cdecl operator delete(void* p)
{
::_free_dbg(p, _NORMAL_BLOCK);
}
inline void __cdecl operator delete[](void* p)
{
operator delete(p);
}
inline void __cdecl operator delete(void* p, const char* lpszFileName, int nLine)
{
operator delete(p);
}
inline void __cdecl operator delete[](void* p, const char* lpszFileName, int nLine)
{
operator delete(p);
}
inline void __cdecl operator delete(void *p, const std::nothrow_t&)
{
operator delete(p);
}
inline void __cdecl operator delete[](void *p, const std::nothrow_t&)
{
operator delete(p);
}
#define new new(__FILE__, __LINE__)
#endif // _DEBUG && defined _DETECT_MEMORY_LEAK
#include "stdafx.h"
#include "win32_crtdbg.h"
#if defined _DEBUG && defined _DETECT_MEMORY_LEAK
__dbg_impl::CDebugEnv __dbgEnv;
#endif // _DEBUG && defined _DETECT_MEMORY_LEAK