检测由new/delete使用不当引起的内存泄露

http://blog.csdn.net/joyzml/article/details/6394089


检测由new/delete使用不当引起的内存泄露

分类:  wince应用程序2011-05-04 15:13  1186人阅读  评论(2)  收藏  举报

=============================================================

标题:检测由new/delete使用不当引起的内存泄露

备注:wince

日期:2011.5.4

姓名:朱铭雷

=============================================================

以前在网上看到过wince下可用的检测new/delete的小程序,不过好像在mfc下使用还有点问题。但实在是不记得文章的名字了,也没有找到原文地址。先前开会时,同事也提到了这个事情,一定要严防memory leak。所以凭着一点记忆和对new/delete的一点简单理解,勉强写了这么一个简陋的检测程序。不过这份简陋的程序还是起了作用的,它比较擅长的就是当项目越来越大时,new出来的内存忘记delete,或者是由于没有对某些跳转返回考虑周全而使程序在某些情况下越过了delete,亦或是某些时候这个内存需要同事来释放而双方又没有去沟通时等等产生的内存泄露。正是这份极为简陋的程序,检测出了我们当前项目中几处极为严重的内存泄露,特别是其中一处,几乎是每次执行该功能就会泄露将近1M的宝贵内存。由于这份程序基本上是凭着记忆“参考”网上那位无名大侠的(记得是codeproject上看到的),所以在这里表示感谢。也希望看到俺这篇日记的朋友,能够给点意见,帮助修改错误,填补不足,抑或是这段程序从根本上就是不对的话,重构一个。我实在是实力和时间都不足,希望搞wince的朋友们群策群力,多共享些好用的工具,帮助大家更好的工作。

       下面是这份程序检测到内存泄露,将信息写到了vs的输出窗口:

 

       双击所输出的内存泄露信息,将会跳转到引起内存泄露的相应文件的相应代码行:new_delete_memleak_v11Dlg.cpp文件的第68行。

 

       下面是相关的3个文件的源代码:

[cpp]  view plain copy
  1. /******************************************************************************** 
  2. 文件名       : Ce_MemLeak_Debug.h 
  3. 相关文件     : Ce_MemLeak_Debug.cpp 
  4. 文件实现功能 : 检测由new,delete使用不当造成的内存泄露, 
  5.                可直接定位到导致内存泄露的代码行 
  6. 作者         : zhuyf 
  7. 版本         : 1.1 
  8. 备注         : (1) 存在一定的问题,但不影响目前的检测功能 
  9.                (2) “placement new”合乎常理的写法应该是其内部有一个循环,在循环中尝试 
  10.                分配内存,如果无法找到足够内存,则调用“new-handler”。但本程序并不 
  11.                是打算替换global new/delete,也不打算替换class专属的new/delete,只 
  12.                是为了协助检测new/delete产生的内存泄露,所以不要试图将本程序中重载的 
  13.                new/delete代替原有的new/delete来使用。 
  14.                (3) 此版本针对MFC 
  15. 日期         : 2010-04-26 
  16. 修改记录     : 增加“placement delete”,避免“分配内存成功,而对象构造函数中抛出 
  17.                异常,这时运行期系统在试图寻找placement delete时失败,而导致无法 
  18.                恢复原态,从而导致非常细微难以查找的内存泄露”情况。 
  19. 修改时间     : 2011-05-04 
  20. ********************************************************************************/   
  21. #pragma once  
  22.   
  23. #if defined(_DEBUG) && defined(_WIN32_WCE)  
  24.   
  25. class GarbageCollector  
  26. {  
  27. public:  
  28.     GarbageCollector();  
  29.     ~GarbageCollector();  
  30. };  
  31.   
  32. void* operator new(size_t size, char* pszFileName, int iLineNum);  
  33. void operator delete(void *pMemory, char* pszFileName, int iLineNum);  
  34. void operator delete(void *pMemory);  
  35.   
  36. #undef DEBUG_NEW  
  37. #define DEBUG_NEW ::new (__FILE__, __LINE__)  
  38.   
  39. extern GarbageCollector g_GC;  
  40.   
  41. #endif // if defined(_DEBUG) && defined(_WIN32_WCE)  
[cpp]  view plain copy
  1. /******************************************************************************** 
  2. 文件名       : Ce_MemLeak_Debug.cpp 
  3. 相关文件     : Ce_MemLeak_Debug.h 
  4. 文件实现功能 : 检测由new,delete使用不当造成的内存泄露, 
  5.                可直接定位到导致内存泄露的代码行 
  6. 作者         : zhuyf 
  7. 版本         : 1.1 
  8. 备注         : (1) 存在一定的问题,但不影响目前的检测功能 
  9.                (2) “placement new”合乎常理的写法应该是其内部有一个循环,在循环中尝试 
  10.                分配内存,如果无法找到足够内存,则调用“new-handler”。但本程序并不 
  11.                是打算替换global new/delete,也不打算替换class专属的new/delete,只 
  12.                是为了协助检测new/delete产生的内存泄露,所以不要试图将本程序中重载的 
  13.                new/delete代替原有的new/delete来使用。 
  14.                (3) 此版本针对MFC 
  15. 日期         : 2010-04-26 
  16. 修改记录     : 增加“placement delete”,避免“分配内存成功,而对象构造函数中抛出 
  17.                异常,这时运行期系统在试图寻找placement delete时失败,而导致无法 
  18.                恢复原态,从而导致非常细微难以查找的内存泄露”情况。 
  19. 修改时间     : 2011-05-04 
  20. ********************************************************************************/   
  21. #include "stdafx.h"  
  22. #include "Ce_MemLeak_Debug.h"  
  23.   
  24. #if defined(_DEBUG) && defined(_WIN32_WCE)  
  25.   
  26. typedef struct _FILENAME  
  27. {  
  28.     char* szFileName;  
  29.     _FILENAME* pNextFile;  
  30. }FILENAME, *PFILENAME;  
  31.   
  32. typedef struct _MEMINFO  
  33. {  
  34.     PFILENAME pFileName;  
  35.     int iLineNum;  
  36.     UINT nMemLen;  
  37.     void* pMemAddr;  
  38.     _MEMINFO* pNextMemInfo;  
  39. }MEMINFO, *PMEMINFO;  
  40.   
  41. GarbageCollector g_GC;  
  42. PMEMINFO g_pMemInfoRoot = 0;  
  43. PFILENAME g_pFileNameRoot = 0;  
  44.   
  45. void* operator new(size_t size, char* pszFileName, int iLineNum)  
  46. {  
  47.     void* pMem = malloc(size);  
  48.     if (pMem)  
  49.     {  
  50.         PMEMINFO pMemInfo = (PMEMINFO)malloc(sizeof(MEMINFO));  
  51.         pMemInfo->iLineNum = iLineNum;  
  52.         pMemInfo->nMemLen = size;  
  53.         pMemInfo->pMemAddr = pMem;  
  54.         pMemInfo->pNextMemInfo = 0;  
  55.   
  56.         PFILENAME pTmpFileName = NULL;  
  57.         for (pTmpFileName = g_pFileNameRoot; pTmpFileName && strcmp(pszFileName, pTmpFileName->szFileName); pTmpFileName = pTmpFileName->pNextFile);  
  58.         if (!pTmpFileName)  
  59.         {  
  60.             char* pszName = (char*)malloc((strlen(pszFileName) + 1) * sizeof(char));  
  61.             strcpy(pszName, pszFileName);  
  62.             PFILENAME pFileName = (PFILENAME)malloc(sizeof (FILENAME));  
  63.             pFileName->szFileName = pszName;  
  64.             pFileName->pNextFile = 0;  
  65.             if (!g_pFileNameRoot)  
  66.             {  
  67.                 g_pFileNameRoot = pFileName;  
  68.             }  
  69.             else  
  70.             {  
  71.                 for (pTmpFileName = g_pFileNameRoot; pTmpFileName->pNextFile; pTmpFileName = pTmpFileName->pNextFile);  
  72.                 pTmpFileName->pNextFile = pFileName;  
  73.             }  
  74.             pTmpFileName = pFileName;  
  75.         }  
  76.         pMemInfo->pFileName = pTmpFileName;  
  77.   
  78.         if (!g_pMemInfoRoot)  
  79.         {  
  80.             g_pMemInfoRoot = pMemInfo;  
  81.         }  
  82.         else  
  83.         {  
  84.             PMEMINFO pTmpMemInfo = NULL;  
  85.             for (pTmpMemInfo = g_pMemInfoRoot; pTmpMemInfo->pNextMemInfo; pTmpMemInfo = pTmpMemInfo->pNextMemInfo);  
  86.             pTmpMemInfo->pNextMemInfo = pMemInfo;  
  87.         }  
  88.     }  
  89.     return pMem;  
  90. }  
  91.   
  92. void operator delete(void *pMemory, char* pszFileName, int iLineNum)  
  93. {  
  94.     if (pMemory)  
  95.     {  
  96.         PMEMINFO pTmpMemInfo = 0;  
  97.         if (g_pMemInfoRoot)  
  98.         {  
  99.             if (pMemory == g_pMemInfoRoot->pMemAddr)  
  100.             {  
  101.                 pTmpMemInfo = g_pMemInfoRoot;  
  102.                 g_pMemInfoRoot = g_pMemInfoRoot->pNextMemInfo;  
  103.                 free(pTmpMemInfo);  
  104.             }  
  105.             else  
  106.             {  
  107.                 for (pTmpMemInfo = g_pMemInfoRoot; pTmpMemInfo->pNextMemInfo && (pTmpMemInfo->pNextMemInfo->pMemAddr != pMemory); pTmpMemInfo = pTmpMemInfo->pNextMemInfo);  
  108.                 if (pTmpMemInfo->pNextMemInfo)  
  109.                 {  
  110.                     PMEMINFO pTmp2MemInfo;  
  111.                     pTmp2MemInfo = pTmpMemInfo->pNextMemInfo;  
  112.                     pTmpMemInfo->pNextMemInfo = pTmp2MemInfo->pNextMemInfo;  
  113.                     free(pTmp2MemInfo);  
  114.                 }  
  115.                 else  
  116.                 {  
  117.                     // NKDbgPrintfW(_T("%s(%i) : Warning : deletes memory pointer not allocated with new!/n"), _T(__FILE__), __LINE__);  
  118.                 }  
  119.             }  
  120.             free (pMemory);  
  121.         }         
  122.     }  
  123. }  
  124.   
  125.   
  126. void operator delete(void *pMemory)  
  127. {  
  128.     if (pMemory)  
  129.     {  
  130.         PMEMINFO pTmpMemInfo = 0;  
  131.         if (g_pMemInfoRoot)  
  132.         {  
  133.             if (pMemory == g_pMemInfoRoot->pMemAddr)  
  134.             {  
  135.                 pTmpMemInfo = g_pMemInfoRoot;  
  136.                 g_pMemInfoRoot = g_pMemInfoRoot->pNextMemInfo;  
  137.                 free(pTmpMemInfo);  
  138.             }  
  139.             else  
  140.             {  
  141.                 for (pTmpMemInfo = g_pMemInfoRoot; pTmpMemInfo->pNextMemInfo && (pTmpMemInfo->pNextMemInfo->pMemAddr != pMemory); pTmpMemInfo = pTmpMemInfo->pNextMemInfo);  
  142.                 if (pTmpMemInfo->pNextMemInfo)  
  143.                 {  
  144.                     PMEMINFO pTmp2MemInfo;  
  145.                     pTmp2MemInfo = pTmpMemInfo->pNextMemInfo;  
  146.                     pTmpMemInfo->pNextMemInfo = pTmp2MemInfo->pNextMemInfo;  
  147.                     free(pTmp2MemInfo);  
  148.                 }  
  149.                 else  
  150.                 {  
  151.                     // NKDbgPrintfW(_T("%s(%i) : Warning : deletes memory pointer not allocated with new!/n"), _T(__FILE__), __LINE__);  
  152.                 }  
  153.             }  
  154.             free (pMemory);  
  155.         }         
  156.     }  
  157. }  
  158.   
  159. GarbageCollector::GarbageCollector()  
  160. {  
  161.   
  162. }  
  163.   
  164. GarbageCollector::~GarbageCollector ()  
  165. {  
  166.     USES_CONVERSION;  
  167.     if (!g_pMemInfoRoot)  
  168.     {  
  169.         NKDbgPrintfW (_T("------------------------------------------------------------------------------------/n"));  
  170.         NKDbgPrintfW(_T("-----------------------------No memory leaks detected!------------------------------/n"));  
  171.         NKDbgPrintfW (_T("------------------------------------------------------------------------------------/n"));  
  172.     }  
  173.     else  
  174.     {  
  175.         PMEMINFO pTmpMemInfo = NULL;  
  176.         NKDbgPrintfW (_T("------------------------------------------------------------------------------------/n"));  
  177.         NKDbgPrintfW (_T("-------------------------------Detected memory leaks!-------------------------------/n"));  
  178.         NKDbgPrintfW (_T("------------------------------------------------------------------------------------/n"));  
  179.         for (pTmpMemInfo = g_pMemInfoRoot; pTmpMemInfo; pTmpMemInfo = pTmpMemInfo->pNextMemInfo)  
  180.         {  
  181.             NKDbgPrintfW(_T("%s(%i) : normal block at 0x%08X, %i bytes long/n"),  
  182.                 A2W(pTmpMemInfo->pFileName->szFileName),  
  183.                 pTmpMemInfo->iLineNum,  
  184.                 pTmpMemInfo->pMemAddr,  
  185.                 pTmpMemInfo->nMemLen);  
  186.         }  
  187.         NKDbgPrintfW (_T("------------------------------------------------------------------------------------/n"));  
  188.     }  
  189.   
  190.     PFILENAME pTmpFileName = g_pFileNameRoot;  
  191.     for (; pTmpFileName; )  
  192.     {  
  193.         g_pFileNameRoot = pTmpFileName->pNextFile;  
  194.         free(pTmpFileName->szFileName);  
  195.         free(pTmpFileName);  
  196.         pTmpFileName = g_pFileNameRoot;  
  197.     }  
  198. }  
  199.   
  200. #endif // if defined(_DEBUG) && defined(_WIN32_WCE)  
[cpp]  view plain copy
  1. /******************************************************************************** 
  2. 文件名       : Ce_MFC_debug.h 
  3. 相关文件     : Ce_MemLeak_Debug.h Ce_MemLeak_Debug.cpp 
  4. 文件实现功能 : 配合Ce_MemLeak_Debug.h Ce_MemLeak_Debug.cpp使用 
  5. 作者         : zhuyf 
  6. 版本         : 1.0 
  7. 备注         : 无 
  8. 日期         : 2010-04-26 
  9. 修改记录     : 无 
  10. ********************************************************************************/   
  11. #pragma once  
  12.   
  13. #ifdef _DEBUG  
  14. #define new DEBUG_NEW  
  15. #endif  

       使用方法应该是非常简单的,可以在stdafx.h头文件中加入#include "Ce_MemLeak_Debug.h",在需要的.cpp文件中加入#include "Ce_MFC_debug.h"。之后充分!运行程序。在程序退出时,就会将“内存泄露信息”写到Debug输出窗口。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值