zoukankan      html  css  js  c++  java
  • C++内存泄露的检测(三)

    一 简单的对内存的分配和释放跟踪,并将结果输出到console,它也是一般C++内存泄露的检测原理,来自C++编程思想:
    (比较简单,大家都可以看的明白的哦)实现如下:

    MemCheck.h

    //: C02:MemCheck.h
    #ifndef MEMCHECK_H
    #define MEMCHECK_H
    #include <cstddef>  // for size_t
    
    // Hijack the new operator (both scalar and array versions)
    void* operator new(std::size_t, const char*, long);
    void* operator new[](std::size_t, const char*, long);
    #define new new (__FILE__, __LINE__)
    
    extern bool traceFlag;
    #define TRACE_ON() traceFlag = true
    #define TRACE_OFF() traceFlag = false
    
    extern bool activeFlag;
    #define MEM_ON() activeFlag = true
    #define MEM_OFF() activeFlag = false
    
    #endif
    

     MemCheck.cpp

    //: C02:MemCheck.cpp {O}
    #include <cstdio>
    #include <cstdlib>
    #include <cassert>
    using namespace std;
    #undef new
    
    // Global flags set by macros in MemCheck.h
    bool traceFlag = true;
    bool activeFlag = false;
    
    namespace {
    
    // Memory map entry type
    struct Info {
      void* ptr;
      const char* file;
      long line;
    };
    
    // Memory map data
    const size_t MAXPTRS = 10000u;
    Info memMap[MAXPTRS];
    size_t nptrs = 0;
    
    // Searches the map for an address
    int findPtr(void* p) 
    {
      for (int i = 0; i < nptrs; ++i)
        if (memMap[i].ptr == p)
          return i;
      return -1;
    }
    
    void delPtr(void* p)
    {
      int pos = findPtr(p);
      assert(p >= 0);
      // Remove pointer from map
      for (size_t i = pos; i < nptrs-1; ++i)
        memMap[i] = memMap[i+1];
      --nptrs;
    }
    
    // Dummy type for static destructor
    struct Sentinel 
    {
      ~Sentinel()
      {
        if (nptrs > 0) 
        {
          printf("Leaked memory at:\n");
          for (size_t i = 0; i < nptrs; ++i)
            printf("\t%p (file: %s, line %ld)\n",
              memMap[i].ptr, memMap[i].file, memMap[i].line);
        }
        else
          printf("No user memory leaks!\n");
      }
    };
    
    // Static dummy object
    Sentinel s;
    
    } // End anonymous namespace
    
    // Overload scalar new
    void* operator new(size_t siz, const char* file,
      long line) {
      void* p = malloc(siz);
      if (activeFlag)
      {
        if (nptrs == MAXPTRS)
        {
          printf("memory map too small (increase MAXPTRS)\n");
          exit(1);
        }
        memMap[nptrs].ptr = p;
        memMap[nptrs].file = file;
        memMap[nptrs].line = line;
        ++nptrs;
      }
      if (traceFlag) 
      {
        printf("Allocated %u bytes at address %p ", siz, p);
        printf("(file: %s, line: %ld)\n", file, line);
      }
      return p;
    }
    
    // Overload array new
    void* operator new[](size_t siz, const char* file,
      long line) {
      return operator new(siz, file, line);
    }
    
    // Override scalar delete
    void operator delete(void* p) 
    {
      if (findPtr(p) >= 0) 
      {
        free(p);
        assert(nptrs > 0);
        delPtr(p);
        if (traceFlag)
          printf("Deleted memory at address %p\n", p);
      }
      else if (!p && activeFlag)
        printf("Attempt to delete unknown pointer: %p\n", p);
    }
    
    // Override array delete
    void operator delete[](void* p) {
      operator delete(p);
    } /**////:~
    

     二 说明:
    1)通过重载new和delete来实现
    2)使用时需要在工程中加入MemCheck.h和MemCheck.cpp,在需要检测的文件的前面include “MemCheck.h”,但是必须在所有的include的最后。
    3)MEM_ON(),MEM_OFF()用来打开或关闭检测
    4)TRACE_ON(),和TRACE_OFF()用来打开或关闭检测结果的输出
    5)可以检测代码中使用了流,标准容器,以及某个类的构造函数分配了空间

    三 使用实例:
    console 的project中加入下面的file:

    // MemoryLeak3.cpp : Defines the entry point for the console application.
    //
    
    #include <iostream>
    #include <vector>
    #include <cstring>
    
    #include "MemCheck.h"   // Must appear last!
    using namespace std;
    
    void Test()
    {
        int *i = new int(0);
    }
    
    class MyClass
    {
    private:
        int *p;
    public:
        MyClass()
        {
            if(p != NULL)
            {
                p = new int(0);
            }
        }
        ~MyClass()
        {
            if(p != NULL)
            {
                delete p;
                p = NULL;
            }
        }
    };
    
    void Test2()
    {
        int *i = NULL; // better for read
            i = new int(0);    
            int *&y = i; // pointer's reference
            delete i;
    
            MyClass *pMyClass = new MyClass();
    
            std::vector<MyClass*> myClasses;
            myClasses.push_back(new MyClass());
            myClasses.push_back(new MyClass());
    
            std::vector<void*> myVector;
            myVector.push_back(new MyClass());
            myVector.push_back(new MyClass());
            delete (MyClass *)(myVector.at(0));
            delete myVector.at(1); // memory leak
    }
    
    class Foo 
    {
      char* s;
    public:
      Foo(const char*s ) 
      {
        this->s = new char[strlen(s) + 1];
        strcpy(this->s, s);
      }
      ~Foo() 
      {
        delete [] s;
      }
    };
    void Test3()
    {
        cout << "hello\n";
        int* p = new int;
        delete p;
        int* q = new int[3];
        delete [] q;
        int* r;
        /**//*delete r;*/
        vector<int> v;
        v.push_back(1);
        Foo s("goodbye");
    }
    int main() 
    {
        TRACE_OFF();
        MEM_ON();
        Test();
        Test2();
        Test3();
        MEM_OFF();
    } /**////:~
    

     四 测试结果如下

  • 相关阅读:
    【笔记】程序员编程艺术 字符串转换成整数
    解决Eclipse 项目报错:Unbound classpath container: ‘JRE System Library [JavaSE-1.7]
    python_day1(初始Python)
    ActiveMQ 复杂类型的发布与订阅
    win8.1 Framework3.5安装不上的问题
    JVM探秘:内存溢出
    JVM探秘:Java对象
    JVM探秘:Java内存区域
    Vmware安装的linux系统开机黑屏,点关闭就显示虚拟机忙怎么怎么解决?
    Java基础--面向对象(上)
  • 原文地址:https://www.cnblogs.com/FCoding/p/2576877.html
Copyright © 2011-2022 走看看