内存泄露是许多大规模程序中亟待解决的问题,下面是一点资料整理,帮我记忆吧。有VC自带的工具,也有免费的比较成熟的工具。控制台程序编译即可看到效果。
// = MemoryLeakDetect.cpp
/// 去掉注释观察VS2005自带内存检测工具效果
//
#define DEFAULT_CRGDBG_MEM_CHECK
#ifndef DEFAULT_CRGDBG_MEM_CHECK
// = vld内存泄露检测
/// http://www.codeproject.com/tools/visualleakdetector.asp
/// Visual Leak Detector - Enhanced Memory Leak Detection for Visual C++
#include < vld.h >
#else
// = VS2005自带内存检测设施
/// http://www.vckbase.com/document/viewdoc/?id=1349
/// VC++ 6.0 中如何使用 CRT 调试功能来检测内存泄漏
#define _CRTDBG_MAP_ALLOC
#include < stdlib.h >
#include < crtdbg.h >
/// 确定准确的内存泄露位置
#include " debug_new.h "
#endif
// = UNICODE or ANSI
#include < tchar.h >
#include < strsafe.h >
void MemoryLeakDetectDemo()
{
const _TCHAR str[] = _T( " Hello the world! Hello the children! " );
_TCHAR * p = new _TCHAR[ 128 ];
size_t size = 0 ;
StringCchLength(str, 1024 , & size);
StringCchCopy(p, size, str);
}
int _tmain( int argc, _TCHAR * argv[])
{
#ifdef DEFAULT_CRGDBG_MEM_CHECK
#ifndef DEFAULT_CRGDBG_MEM_CHECK
// = vld内存泄露检测
/// http://www.codeproject.com/tools/visualleakdetector.asp
/// Visual Leak Detector - Enhanced Memory Leak Detection for Visual C++
#include < vld.h >
#else
// = VS2005自带内存检测设施
/// http://www.vckbase.com/document/viewdoc/?id=1349
/// VC++ 6.0 中如何使用 CRT 调试功能来检测内存泄漏
#define _CRTDBG_MAP_ALLOC
#include < stdlib.h >
#include < crtdbg.h >
/// 确定准确的内存泄露位置
#include " debug_new.h "
#endif
// = UNICODE or ANSI
#include < tchar.h >
#include < strsafe.h >
void MemoryLeakDetectDemo()
{
const _TCHAR str[] = _T( " Hello the world! Hello the children! " );
_TCHAR * p = new _TCHAR[ 128 ];
size_t size = 0 ;
StringCchLength(str, 1024 , & size);
StringCchCopy(p, size, str);
}
int _tmain( int argc, _TCHAR * argv[])
{
#ifdef DEFAULT_CRGDBG_MEM_CHECK
/// 程序无论从何种路径退出都会自动调用_CrtDumpMemoryLeaks
///_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
MemoryLeakDetectDemo();
#ifdef DEFAULT_CRGDBG_MEM_CHECK
_CrtDumpMemoryLeaks();
#endif
return 0 ;
}
///_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
MemoryLeakDetectDemo();
#ifdef DEFAULT_CRGDBG_MEM_CHECK
_CrtDumpMemoryLeaks();
#endif
return 0 ;
}
//
= debug_new.h
#ifndef _DEBUG_NEW_H_
#define _DEBUG_NEW_H_
#ifdef _DEBUG
#undef new
extern void _RegDebugNew( void );
extern void * __cdecl operator new ( size_t, const char * , int );
extern void __cdecl operator delete( void * , const char * , int );
#define new new(__FILE__, __LINE__)
#define REG_DEBUG_NEW _RegDebugNew();
#else
#define REG_DEBUG_NEW
#endif // _DEBUG
#endif // _DEBUG_NEW_H_
#ifndef _DEBUG_NEW_H_
#define _DEBUG_NEW_H_
#ifdef _DEBUG
#undef new
extern void _RegDebugNew( void );
extern void * __cdecl operator new ( size_t, const char * , int );
extern void __cdecl operator delete( void * , const char * , int );
#define new new(__FILE__, __LINE__)
#define REG_DEBUG_NEW _RegDebugNew();
#else
#define REG_DEBUG_NEW
#endif // _DEBUG
#endif // _DEBUG_NEW_H_
/*
**********************************************************************
*/
/* comment: 此文件与debug_new.h配合使用,用于在调试期发现内存泄漏 */
/* 仅在VC++编译器中适用(包括Intel C++,因为它使用了相同的库) */
/* 作者: 周星星 http://blog.vckbase.com/bruceteen/ */
/* 版权申明: 无,可任意 使用,修改 和 发布 */
/* ********************************************************************** */
// #include "debug_new.h"
#ifdef _DEBUG
#include < windows.h >
#include < crtdbg.h >
class _CriSec
{
CRITICAL_SECTION criSection;
public :
_CriSec() { InitializeCriticalSection( & criSection ); }
~ _CriSec() { DeleteCriticalSection( & criSection ); }
void Enter() { EnterCriticalSection( & criSection ); }
void Leave() { LeaveCriticalSection( & criSection ); }
} _cs;
void _RegDebugNew( void )
{
_CrtSetDbgFlag( _CRTDBG_REPORT_FLAG | _CRTDBG_LEAK_CHECK_DF );
}
void * __cdecl operator new ( size_t nSize, const char * lpszFileName, int nLine )
{
// comment 1: MFC中提供的debug new虽然加了锁,但我在实际测试的时候发现多线程并发
// 调用的时候还是抛出了系统错误,所以我在这里加了一个线程互斥量.
// comment 2: debug new和debug delete之间需不需要互斥我并不知道,保险起见,我同样
// 加了线程互斥量.
// comment 3: 按照C++标准规定,在operator new失败后应当调用set_new_handler设置的
// 函数,但是MSDN中却说"头文件new中的set_new_handler是stub的,而应该使
// 用头文件new.h中的_set_new_handler",这简直是滑天下之大稽.
// 以下是VC++6.0中的set_new_handler定义:
// new_handler __cdecl set_new_handler( new_handler new_p )
// {
// assert( new_p == 0 ); // cannot use stub to register a new handler
// _set_new_handler( 0 );
// return 0;
// }
// 所以我也无计可施,只能舍弃set_new_handler的作用.
_cs.Enter();
void * p = _malloc_dbg( nSize, _NORMAL_BLOCK, lpszFileName, nLine );
_cs.Leave();
return p;
}
void __cdecl operator delete( void * p, const char * /* lpszFileName */ , int /* nLine */ )
{
_cs.Enter();
_free_dbg( p, _CLIENT_BLOCK );
_cs.Leave();
}
#endif
/* comment: 此文件与debug_new.h配合使用,用于在调试期发现内存泄漏 */
/* 仅在VC++编译器中适用(包括Intel C++,因为它使用了相同的库) */
/* 作者: 周星星 http://blog.vckbase.com/bruceteen/ */
/* 版权申明: 无,可任意 使用,修改 和 发布 */
/* ********************************************************************** */
// #include "debug_new.h"
#ifdef _DEBUG
#include < windows.h >
#include < crtdbg.h >
class _CriSec
{
CRITICAL_SECTION criSection;
public :
_CriSec() { InitializeCriticalSection( & criSection ); }
~ _CriSec() { DeleteCriticalSection( & criSection ); }
void Enter() { EnterCriticalSection( & criSection ); }
void Leave() { LeaveCriticalSection( & criSection ); }
} _cs;
void _RegDebugNew( void )
{
_CrtSetDbgFlag( _CRTDBG_REPORT_FLAG | _CRTDBG_LEAK_CHECK_DF );
}
void * __cdecl operator new ( size_t nSize, const char * lpszFileName, int nLine )
{
// comment 1: MFC中提供的debug new虽然加了锁,但我在实际测试的时候发现多线程并发
// 调用的时候还是抛出了系统错误,所以我在这里加了一个线程互斥量.
// comment 2: debug new和debug delete之间需不需要互斥我并不知道,保险起见,我同样
// 加了线程互斥量.
// comment 3: 按照C++标准规定,在operator new失败后应当调用set_new_handler设置的
// 函数,但是MSDN中却说"头文件new中的set_new_handler是stub的,而应该使
// 用头文件new.h中的_set_new_handler",这简直是滑天下之大稽.
// 以下是VC++6.0中的set_new_handler定义:
// new_handler __cdecl set_new_handler( new_handler new_p )
// {
// assert( new_p == 0 ); // cannot use stub to register a new handler
// _set_new_handler( 0 );
// return 0;
// }
// 所以我也无计可施,只能舍弃set_new_handler的作用.
_cs.Enter();
void * p = _malloc_dbg( nSize, _NORMAL_BLOCK, lpszFileName, nLine );
_cs.Leave();
return p;
}
void __cdecl operator delete( void * p, const char * /* lpszFileName */ , int /* nLine */ )
{
_cs.Enter();
_free_dbg( p, _CLIENT_BLOCK );
_cs.Leave();
}
#endif