【转】c++内存泄露检测,长文慎入!

原文网址:http://blog.csdn.net/zengraoli/article/details/8905334

关于内存泄露的,今天无意想到,网上找了一下

 

本篇blog附带的所有工具和代码下载地址如下:

http://download.csdn.net/detail/zengraoli/5348827

 

文中的memcheck晚点的时候在把它打包成dll

 

一、使用Dbgview.exe

不多数都是用的Dbgview.exe,话说还不错,我一直想找的仅仅是一个检测内存泄露的class,没想到csdn上面问,找到了这么一个工具,参看csdn论坛链接http://bbs.csdn.net/topics/390452307

 

来个测试工程:

 

  1. #include <iostream>  
  2. #include "string"  
  3. #include "vector"  
  4. using namespace std;  
  5.   
  6. int main()  
  7. {  
  8.     {  
  9.         char *str;  
  10.         str = new char[100 + 1];  
  11.   
  12.         strcpy(str, "zengraoli");  
  13.   
  14.         cout << str << endl;  
  15.     }  
  16.   
  17.     _CrtDumpMemoryLeaks();   // 内存泄露检测  
  18.   
  19.     return 0;  
  20. }  

 

 

Ctrl+F5后,在Dbgview.exe中出现了下面的信息:

 

 

Detected memory leaks

这个是提示

 

 

上面的测试不方便的地方:

但在这上面显然有不太好的地方,比如我需要知道哪一行导致的内存泄露,所以参考csdn blog的一篇文章:http://blog.csdn.net/iuhsihsow/article/details/8492363

 

 

再次修改:

  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. #include "string"  
  4. #include "vector"  
  5. using namespace std;  
  6.   
  7. #ifdef  _DEBUG  
  8. #define _CRTDBG_MAP_ALLOC  
  9. #include <stdlib.h>  
  10. #include <crtdbg.h>  
  11. #define newEx   new(_NORMAL_BLOCK, __FILE__, __LINE__)  
  12. #endif  
  13.   
  14. inline void EnableMemLeakCheck()  
  15. {  
  16.     _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);  
  17. }  
  18.   
  19. int _tmain(int argc, _TCHAR* argv[])  
  20. {  
  21.     EnableMemLeakCheck();  
  22.   
  23.     char *str = newEx char[9 + 1];  
  24.   
  25.     cout << str << endl;  
  26.   
  27.     return 0;  
  28. }  

 

 

Ctrl+F5后,在Dbgview.exe中出现了下面的信息:

 

 

可以看到正是25行的地方导致内存泄露的

 

 

 

二、不使用Dbgview.exe,直接使用class

参考文章:http://www.cnblogs.com/FCoding/archive/2012/07/04/2576877.html

Code没来得及细看,能用就是了^_^,方便就行,枉自猜测一下原理----------重载了new和delete,对他俩进行一个计数,并记下行数,两个不为偶数,则就是代表已经出现内存泄露了

 

MemCheck.h:

  1. #ifndef MEMCHECK_H  
  2. #define MEMCHECK_H  
  3. #include <cstddef>  // for size_t  
  4.   
  5. // Hijack the new operator (both scalar and array versions)  
  6. void* operator new(std::size_t, const char*, long);  
  7. void* operator new[](std::size_t, const char*, long);  
  8. #define new new (__FILE__, __LINE__)  
  9.   
  10. extern bool traceFlag;  
  11. #define TRACE_ON() traceFlag = true  
  12. #define TRACE_OFF() traceFlag = false  
  13.   
  14. extern bool activeFlag;  
  15. #define MEM_ON() activeFlag = true  
  16. #define MEM_OFF() activeFlag = false  
  17.   
  18. #endif  

 

MemCheck.cpp:

  1. #include <cstdio>  
  2. #include <cstdlib>  
  3. #include <cassert>  
  4. using namespace std;  
  5. #undef new  
  6.   
  7. // Global flags set by macros in MemCheck.h  
  8. bool traceFlag  = true;  
  9. bool activeFlag = false;  
  10.   
  11. namespace   
  12. {  
  13.     // Memory map entry type  
  14.     struct Info   
  15.     {  
  16.         void* ptr;  
  17.         const char* file;  
  18.         long  line;  
  19.     };  
  20.   
  21.     // Memory map data  
  22.     const  size_t MAXPTRS = 10000u;  
  23.     Info   memMap[MAXPTRS];  
  24.     size_t nptrs = 0;  
  25.   
  26.     // Searches the map for an address  
  27.     int findPtr(void* p)   
  28.     {  
  29.         for (int i = 0; i < nptrs; ++i)  
  30.         {  
  31.             if (memMap[i].ptr == p)  
  32.             {  
  33.                 return i;  
  34.             }  
  35.         }  
  36.         return -1;  
  37.     }  
  38.   
  39.     void delPtr(void* p)  
  40.     {  
  41.         int pos = findPtr(p);  
  42.         assert(p >= 0);  
  43.         // Remove pointer from map  
  44.         for (size_t i = pos; i < nptrs-1; ++i)  
  45.         {  
  46.             memMap[i] = memMap[i+1];  
  47.         }  
  48.         --nptrs;  
  49.     }  
  50.   
  51.     // Dummy type for static destructor  
  52.     struct Sentinel   
  53.     {  
  54.         ~Sentinel()  
  55.         {  
  56.             if (nptrs > 0)   
  57.             {  
  58.                 printf("Leaked memory at:\n");  
  59.                 for (size_t i = 0; i < nptrs; ++i)  
  60.                 {  
  61.                     printf("\t%p (file: %s, line %ld)\n",   
  62.                             memMap[i].ptr, memMap[i].file, memMap[i].line);  
  63.                 }  
  64.             }  
  65.             else  
  66.             {  
  67.                 printf("No user memory leaks!\n");  
  68.             }                 
  69.         }  
  70.     };  
  71.   
  72.     // Static dummy object  
  73.     Sentinel s;  
  74.   
  75. // End anonymous namespace  
  76.   
  77. // Overload scalar new  
  78. void* operator new(size_t siz, const char* file,  
  79.                    long line)   
  80. {  
  81.     void* p = malloc(siz);  
  82.     if (activeFlag)  
  83.     {  
  84.         if (nptrs == MAXPTRS)  
  85.         {  
  86.             printf("memory map too small (increase MAXPTRS)\n");  
  87.             exit(1);  
  88.         }  
  89.         memMap[nptrs].ptr = p;  
  90.         memMap[nptrs].file = file;  
  91.         memMap[nptrs].line = line;  
  92.         ++nptrs;  
  93.     }  
  94.     if (traceFlag)   
  95.     {  
  96.         printf("Allocated %u bytes at address %p ", siz, p);  
  97.         printf("(file: %s, line: %ld)\n", file, line);  
  98.     }  
  99.     return p;  
  100. }  
  101.   
  102. // Overload array new  
  103. void* operator new[](size_t siz, const char* file,  
  104.                      long line)  
  105. {  
  106.     return operator new(siz, file, line);  
  107. }  
  108.   
  109. // Override scalar delete  
  110. void operator delete(void* p)   
  111. {  
  112.     if (findPtr(p) >= 0)   
  113.     {  
  114.         free(p);  
  115.         assert(nptrs > 0);  
  116.         delPtr(p);  
  117.         if (traceFlag)  
  118.         {  
  119.             printf("Deleted memory at address %p\n", p);  
  120.         }  
  121.     }  
  122.     else if (!p && activeFlag)  
  123.     {  
  124.         printf("Attempt to delete unknown pointer: %p\n", p);  
  125.     }     
  126. }  
  127.   
  128. // Override array delete  
  129. void operator delete[](void* p)  
  130. {  
  131.     operator delete(p);  
  132. }  

 

那哥们的测试工程,挺不错的,有3种情况:

  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. #include <vector>  
  4. #include <cstring>  
  5.   
  6. #include "MemCheck.h"   // Must appear last!  
  7. using namespace std;  
  8.   
  9. void Test()  
  10. {  
  11.     int *i = new int(0);  
  12. }  
  13.   
  14. class MyClass  
  15. {  
  16. private:  
  17.     int *p;  
  18. public:  
  19.     MyClass()  
  20.     {  
  21.         if(p != NULL)  
  22.         {  
  23.             p = new int(0);  
  24.         }  
  25.     }  
  26.     ~MyClass()  
  27.     {  
  28.         if(p != NULL)  
  29.         {  
  30.             delete p;  
  31.             p = NULL;  
  32.         }  
  33.     }  
  34. };  
  35.   
  36. void Test2()  
  37. {  
  38.     int *i = NULL;  // better for read  
  39.     i = new int(0);      
  40.     int *&y = i;    // pointer's reference  
  41.     delete i;  
  42.   
  43.     MyClass *pMyClass = new MyClass();  
  44.   
  45.     std::vector<MyClass*> myClasses;  
  46.     myClasses.push_back(new MyClass());  
  47.     myClasses.push_back(new MyClass());  
  48.   
  49.     std::vector<void*> myVector;  
  50.     myVector.push_back(new MyClass());  
  51.     myVector.push_back(new MyClass());  
  52.     delete (MyClass *)(myVector.at(0));  
  53.     delete myVector.at(1); // memory leak  
  54. }  
  55.   
  56. class Foo   
  57. {  
  58.     char* s;  
  59. public:  
  60.     Foo(const char*s )   
  61.     {  
  62.         this->s = new char[strlen(s) + 1];  
  63.         strcpy(this->s, s);  
  64.     }  
  65.     ~Foo()   
  66.     {  
  67.         delete [] s;  
  68.     }  
  69. };  
  70.   
  71. void Test3()  
  72. {  
  73.     cout << "hello\n";  
  74.     int* p = new int;  
  75.     delete p;  
  76.     int* q = new int[3];  
  77.     delete [] q;  
  78.     /**//*delete r;*/  
  79.     vector<int> v;  
  80.     v.push_back(1);  
  81.     Foo s("goodbye");  
  82. }  
  83.   
  84. int main()   
  85. {  
  86.     TRACE_OFF();  
  87.     MEM_ON();  
  88.     Test();  
  89.     Test2();  
  90.     Test3();  
  91.     MEM_OFF();  
  92. }  

 

在我编译的时候,会出现一下提示:

 

 

运行的时候出现:

 

 

对这个cpp的使用说明:

 

1、使用时在工程中加入在MemCheck.h,而且这个.h文件应该放在所以头文件的后边,因为里面有这么一句代码:#undef new

2、用MEM_ON()和MEM_OFF()来打开和关闭检测

3、TRACE_ON()和TRACE_OFF()用来打开或关闭检测结果的输出(上面的测试代码中使用没做检测结果的输出)

4、可以检测代码中使用了流、标准容器,以及某个类的构造函数分配了空间

 

posted on 2015-01-28 22:29  wi100sh  阅读(262)  评论(0编辑  收藏  举报

导航