关于内存泄漏的检查网上有很多的例子和代码,其基本的方法都是用宏,替换掉内存分配以及释放的函数。但是现在网上很多的例子中没有一个是适合我们公司的需求的。
具体的对内存泄漏检查有如下要求:
1. 内存泄漏检查的代码尽可能少的占用CPU及内存
2. 尽可能的不影响原程序
因为,我们的服务器程序有泄漏而且是特殊情况下会泄漏,平时很难模拟出来。
对于这种情况下的内存泄漏我以前的做法如下:
1. 用写文件的方法记录所有的内存分配以及释放的操作
2. 再写一个工具去分析所有的记录,从中找出泄漏的代码
这样做需要大量的硬盘空间,不过,这个无所谓了现在硬盘很便宜!
不过需要考虑到服务器程序当中包含了exe以及多个dll,为了通用,内存泄漏检查分为下面几个部分:
1. IMemLeak.h IMemLeak.cpp 加入每一个模块当中
2. MemLeakLog.dll 统一记录所有的内存操作,将其记录到文件当中
3. MemCheckTool.exe 分析工具
//IMemLeak.h #ifndef _YG_MEMDBG_H_ #define _YG_MEMDBG_H_ #include <cstdlib> //Redefines #define malloc(size) mallocb(size, __FILE__, __LINE__) #define free(memblock) freeb(memblock, __FILE__, __LINE__) #define realloc(memblock, size) reallocb(memblock, size, __FILE__, __LINE__) #define calloc(num, size) callocb(num, size, __FILE__, __LINE__) //Redefined functions void * mallocb(size_t size, const char *pszFile, int nLine); void freeb(void *memblock, const char *pszFile, int nLine); void * reallocb(void *memblock, size_t size, const char *pszFile, int nLine); void * callocb(size_t num, size_t size, const char *pszFile, int nLine); //For C++ void * operator new(size_t size, const char *pszFile, int nLine); void * operator new[](size_t size, const char *pszFile, int nLine); void operator delete(void *pvMem) throw(); void operator delete[](void *pvMem) throw(); void pre_delete(const char *pszFile, int nLine); //Redefine new and delete #define new new(__FILE__, __LINE__) #define delete pre_delete(__FILE__, __LINE__),delete #endif
//IMemLeak.cpp #include <stdio.h> #include <tchar.h> #include <stdlib.h> #include <malloc.h> #include <Windows.h> #include <cstdlib> enum EOperateType { Type_Malloc, Type_Calloc, Type_Realloc, Type_New, Type_New_Array, Type_Free, Type_Delete, Type_Delete_Array }; typedef void (__stdcall * pFun_MemLeakLog)(LPCSTR PLog); pFun_MemLeakLog MemLeakLog = NULL; void CheckMemLeakLogDLL() { if (MemLeakLog == NULL) { HINSTANCE hinstLib = LoadLibrary(_T("MemLeakLog.dll")); if (hinstLib != NULL) { MemLeakLog = (pFun_MemLeakLog)GetProcAddress(hinstLib, "MemLeakLog"); } } } void Log(EOperateType type, void * pmem, size_t size, int nLine, const char* pszFile) { CheckMemLeakLogDLL(); char temp[1024]; if (MemLeakLog != NULL) { memset(temp, 0, 1024); sprintf_s(temp, 1024, "%d-%p-%d-%d [%s]\n", type, pmem, size, nLine, pszFile); MemLeakLog(temp); } } void * mallocb(size_t size, const char *pszFile, int nLine) { void * pRet = malloc(size); Log(Type_Malloc, pRet, size, nLine, pszFile); return pRet; } void * callocb(size_t num, size_t size, const char *pszFile, int nLine) { void * pRet = calloc(num, size); Log(Type_Calloc, pRet, size, nLine, pszFile); return pRet; } void freeb(void *memblock, const char *pszFile, int nLine) { if (memblock) { Log(Type_Free, memblock, 0, 0, "NULL"); } free(memblock); } void * reallocb(void *memblock, size_t size, const char *pszFile, int nLine) { void * pRet; pRet = realloc(memblock, size); Log(Type_Free, memblock, size, nLine, pszFile); Log(Type_Realloc, pRet, size, nLine, pszFile); return pRet; } void * operator new(size_t size, const char *pszFile, int nLine) { void * pRet = malloc(size); Log(Type_New, pRet, size, nLine, pszFile); return pRet; } void * operator new[](size_t size, const char *pszFile, int nLine) { void * pRet = malloc(size); Log(Type_New_Array, pRet, size, nLine, pszFile); return pRet; } //#include <new> void operator delete(void *memblock) throw () { if (memblock) { Log(Type_Delete, memblock, 0, 0, "NULL"); } free(memblock); } void operator delete[](void *memblock) throw() { if (memblock) { Log(Type_Delete_Array, memblock, 0, 0, "NULL"); } free(memblock); } void pre_delete(const char *pszFile, int nLine) { }
注意:
a. 输出的目录我是写死了,在D:\MemLeak_Log
b. 在被检查工程里面请增加/FC选项。Project->Properties->Configuration->C/C++->Advanced->Use Full Path Yes(/FC)
c. MemLeakLog.dll 拷贝到与被检查内存泄漏的进程所在的目录下面
我附带上一个例子,大家一看就明白了。