教你如何實(shí)現(xiàn)內(nèi)存泄漏檢查
關(guān)于內(nèi)存泄漏的檢查網(wǎng)上有很多的例子和代碼,其基本的方法都是用宏,替換掉內(nèi)存分配以及釋放的函數(shù)。但是現(xiàn)在網(wǎng)上很多的例子中沒(méi)有一個(gè)是適合我們公司的需求的。
具體的對(duì)內(nèi)存泄漏檢查有如下要求:
1. 內(nèi)存泄漏檢查的代碼盡可能少的占用CPU及內(nèi)存
2. 盡可能的不影響原程序
因?yàn)?,我們的服?wù)器程序有泄漏而且是特殊情況下會(huì)泄漏,平時(shí)很難模擬出來(lái)。
對(duì)于這種情況下的內(nèi)存泄漏我以前的做法如下:
1. 用寫文件的方法記錄所有的內(nèi)存分配以及釋放的操作
2. 再寫一個(gè)工具去分析所有的記錄,從中找出泄漏的代碼
這樣做需要大量的硬盤空間,不過(guò),這個(gè)無(wú)所謂了現(xiàn)在硬盤很便宜!
不過(guò)需要考慮到服務(wù)器程序當(dāng)中包含了exe以及多個(gè)dll,為了通用,內(nèi)存泄漏檢查分為下面幾個(gè)部分:
1. IMemLeak.h IMemLeak.cpp 加入每一個(gè)模塊當(dāng)中
2. MemLeakLog.dll 統(tǒng)一記錄所有的內(nèi)存操作,將其記錄到文件當(dāng)中
3. MemCheckTool.exe 分析工具
- //IMemLeak.h
- #ifndef _YG_MEMDBG_H_
- #define_YG_MEMDBG_H_
- #include <cstdlib>
- //Redefines
- #definemalloc(size) mallocb(size, __FILE__, __LINE__)
- #definefree(memblock) freeb(memblock, __FILE__, __LINE__)
- #definerealloc(memblock, size) reallocb(memblock, size, __FILE__, __LINE__)
- #definecalloc(num, size) callocb(num, size, __FILE__, __LINE__)
- //Redefined functions
- void* mallocb(size_t size, constchar*pszFile, intnLine);
- voidfreeb(void*memblock, constchar*pszFile, intnLine);
- void* reallocb(void*memblock, size_t size, constchar*pszFile, intnLine);
- void* callocb(size_t num, size_t size, constchar*pszFile, intnLine);
- //For C++
- void* operatornew(size_t size, constchar*pszFile, intnLine);
- void* operatornew[](size_t size, constchar*pszFile, intnLine);
- voidoperatordelete(void*pvMem) throw();
- voidoperatordelete[](void*pvMem) throw();
- voidpre_delete(constchar*pszFile, intnLine);
- //Redefine new and delete
- #definenewnew(__FILE__, __LINE__)
- #definedelete 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>
- enumEOperateType
- {
- 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;
- voidCheckMemLeakLogDLL()
- {
- if(MemLeakLog == NULL)
- {
- HINSTANCE hinstLib = LoadLibrary(_T("MemLeakLog.dll"));
- if(hinstLib != NULL)
- {
- MemLeakLog = (pFun_MemLeakLog)GetProcAddress(hinstLib, "MemLeakLog");
- }
- }
- }
- voidLog(EOperateType type, void* pmem, size_t size, intnLine, constchar* pszFile)
- {
- CheckMemLeakLogDLL();
- chartemp[1024];
- if(MemLeakLog != NULL)
- {
- memset(temp, 0, 1024);
- sprintf_s(temp, 1024, "%d-%p-%d-%d [%s] ", type, pmem, size, nLine, pszFile);
- MemLeakLog(temp);
- }
- }
- void* mallocb(size_t size, constchar*pszFile, intnLine)
- {
- void* pRet = malloc(size);
- Log(Type_Malloc, pRet, size, nLine, pszFile);
- returnpRet;
- }
- void* callocb(size_t num, size_t size, constchar*pszFile, intnLine)
- {
- void* pRet = calloc(num, size);
- Log(Type_Calloc, pRet, size, nLine, pszFile);
- returnpRet;
- }
- voidfreeb(void*memblock, constchar*pszFile, intnLine)
- {
- if(memblock)
- {
- Log(Type_Free, memblock, 0, 0, "NULL");
- }
- free(memblock);
- }
- void* reallocb(void*memblock, size_t size, constchar*pszFile, intnLine)
- {
- void* pRet;
- pRet = realloc(memblock, size);
- Log(Type_Free, memblock, size, nLine, pszFile);
- Log(Type_Realloc, pRet, size, nLine, pszFile);
- returnpRet;
- }
- void* operatornew(size_t size, constchar*pszFile, intnLine)
- {
- void* pRet = malloc(size);
- Log(Type_New, pRet, size, nLine, pszFile);
- returnpRet;
- }
- void* operatornew[](size_t size, constchar*pszFile, intnLine)
- {
- void* pRet = malloc(size);
- Log(Type_New_Array, pRet, size, nLine, pszFile);
- returnpRet;
- }
- //#include <new>
- voidoperatordelete(void*memblock) throw()
- {
- if(memblock)
- {
- Log(Type_Delete, memblock, 0, 0, "NULL");
- }
- free(memblock);
- }
- voidoperatordelete[](void*memblock) throw()
- {
- if(memblock)
- {
- Log(Type_Delete_Array, memblock, 0, 0, "NULL");
- }
- free(memblock);
- }
- voidpre_delete(constchar*pszFile, intnLine)
- {
- }
注意:
a. 輸出的目錄我是寫死了,在D:MemLeak_Log
b. 在被檢查工程里面請(qǐng)?jiān)黾?FC選項(xiàng)。Project->Properties->Configuration->C/C++->Advanced->Use Full Path Yes(/FC)
c. MemLeakLog.dll 拷貝到與被檢查內(nèi)存泄漏的進(jìn)程所在的目錄下面
我附帶上一個(gè)例子,大家一看就明白了。
下載地址:http://down.51cto.com/data/236002
原文鏈接:http://www.cnblogs.com/russinovich/archive/2011/08/12/2135625.html
【編輯推薦】
- 發(fā)現(xiàn)Java虛擬機(jī)內(nèi)存泄露問(wèn)題
- 再談讓C++更像C#:C#內(nèi)存泄露問(wèn)題
- 如何發(fā)現(xiàn)客戶端軟件中的內(nèi)存泄露?
- Java內(nèi)存泄露檢測(cè)方法揭秘
- 揭秘Java內(nèi)存泄露與溢出的區(qū)別