基于 crt debug 实现的 Windows 程序内存泄漏检测工具
2013-10-25 22:51
447 查看
要么考虑不周全,一种环境下能用,而在另外一种环境下却不能很好工作,或者漏洞报告的输出方式不合理。
要么过于保守,例如:完全没有必要在 _malloc_dbg() 和 _free_dbg() 的调用前后用 CriticalSection 进行保护(跟踪一下多线程环境下 new 和 malloc 的代码就会明白)。
内存检测主要用到以下几个 API,这些 API 能跟踪 new 和 malloc 系列方法申请的内存,具体说明参考帮助文档:
struct _CrtMemState; _CrtSetDbgFlag(); _CrtMemCheckpoint(); _CrtMemCheckpoint(); _CrtMemDifference(); _CrtMemDumpStatistics(); _malloc_dbg(); _free_dbg();
头文件:win32_crtdbg.h
#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
实现文件:win32_crtdbg.cpp
#include "stdafx.h" #include "win32_crtdbg.h" #if defined _DEBUG && defined _DETECT_MEMORY_LEAK __dbg_impl::CDebugEnv __dbgEnv; #endif // _DEBUG && defined _DETECT_MEMORY_LEAK
使用方法
在 stdafx.h 或其他公共头文件中: #define_DETECT_MEMORY_LEAK,#include"win32_crtdbg.h"。
删除项目工程模板中自动生成的 new 操作符重定义,通常自动生成的 cpp 文件在 DEBUG 环境下会把 new 重定义为 DEBUG_NEW。
存在问题
对于某些全局变量指向的堆内存,如果 ~CDebugEnv() 被调用之时还没释放,则可能存在误报现象。这是一个老大难问题了,目前还没有完美的解决方法。
相关文章推荐
- 基于 crt debug 实现的 Windows 程序内存泄漏检测工具
- Unix下C程序内存泄漏检测工具Valgrind安装与使用
- 【转】Unix下C程序内存泄漏检测工具Valgrind安装与使用
- C++中基于Crt的内存泄漏检测
- 基于Visual C++之Windows核心编程代码分析(3)实现程序自动安装
- 基于tcp raw socket实现的端到端rtt,丢包率检测程序(1)
- c++基于CRT内存泄漏检测
- Windows 内存泄漏检测工具——LeakDiag
- Unix下C程序内存泄漏检测工具Valgrind安装与使用
- 基于Visual C++之Windows核心编程代码分析(3)实现程序自动安装
- Valgrind linux程序内存泄漏检测工具
- Unix下C程序内存泄漏检测工具Valgrind安装与使用
- Unix下C程序内存泄漏检测工具Valgrind安装与使用
- 基于Visual C++之Windows核心编程代码分析(3)实现程序自动安装
- Windows 7 下 vs2010内存泄漏检测工具VLD的使用
- C++中基于Crt的内存泄漏检测
- Unix下C程序内存泄漏检测工具Valgrind安装与使用
- C++中基于Crt的内存泄漏检测(重载new和delete,记录在Map里)
- Windows 内存泄漏检测工具——LeakDiag 详解
- Unix下C程序内存泄漏检测工具Valgrind安装与使用