zoukankan      html  css  js  c++  java
  • 【转】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: ");  
    59.                 for (size_t i = 0; i < nptrs; ++i)  
    60.                 {  
    61.                     printf(" %p (file: %s, line %ld) ",   
    62.                             memMap[i].ptr, memMap[i].file, memMap[i].line);  
    63.                 }  
    64.             }  
    65.             else  
    66.             {  
    67.                 printf("No user memory leaks! ");  
    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) ");  
    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) ", 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 ", p);  
    120.         }  
    121.     }  
    122.     else if (!p && activeFlag)  
    123.     {  
    124.         printf("Attempt to delete unknown pointer: %p ", 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 ";  
    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、可以检测代码中使用了流、标准容器,以及某个类的构造函数分配了空间

  • 相关阅读:
    预习作业一
    20145234黄斐《java程序设计基础》第一周
    预习作业3
    开源 人脸识别 openface 实用介绍 实例演示 训练自己的模型
    ubuntu 开机 输入密码 无法进入
    linux anaconda 管理 python 包
    如何从零开始做一个蓝牙机械键盘
    keil中结构体跨文件调用
    GPRS 通信
    如何查找EI 及SCI 索引
  • 原文地址:https://www.cnblogs.com/wi100sh/p/4257304.html
Copyright © 2011-2022 走看看