程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> c++內存洩露檢測,長文慎入!

c++內存洩露檢測,長文慎入!

編輯:C++入門知識

關於內存洩露的,今天無意想到,網上找了一下

 


文中的memcheck晚點的時候在把它打包成dll

 

來個測試工程:

[cpp]
#include <iostream>  
#include "string"  
#include "vector"  
using namespace std; 
 
int main() 

    { 
        char *str; 
        str = new char[100 + 1]; 
 
        strcpy(str, "zengraoli"); 
 
        cout << str << endl; 
    } 
 
    _CrtDumpMemoryLeaks();   // 內存洩露檢測  
 
    return 0; 

#include <iostream>
#include "string"
#include "vector"
using namespace std;

int main()
{
 {
  char *str;
  str = new char[100 + 1];

  strcpy(str, "zengraoli");

  cout << str << endl;
 }

 _CrtDumpMemoryLeaks();   // 內存洩露檢測

 return 0;
}


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

 

 \
 

 

Detected memory leaks

這個是提示

 

 再次修改:
[cpp] 
#include "stdafx.h"  
#include <iostream>  
#include "string"  
#include "vector"  
using namespace std; 
 
#ifdef  _DEBUG  
#define _CRTDBG_MAP_ALLOC  
#include <stdlib.h>  
#include <crtdbg.h>  
#define newEx   new(_NORMAL_BLOCK, __FILE__, __LINE__)  
#endif  
 
inline void EnableMemLeakCheck() 

    _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); 

 
int _tmain(int argc, _TCHAR* argv[]) 

    EnableMemLeakCheck(); 
 
    char *str = newEx char[9 + 1]; 
 
    cout << str << endl; 
 
    return 0; 

#include "stdafx.h"
#include <iostream>
#include "string"
#include "vector"
using namespace std;

#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#define newEx   new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif

inline void EnableMemLeakCheck()
{
 _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
}

int _tmain(int argc, _TCHAR* argv[])
{
 EnableMemLeakCheck();

 char *str = newEx char[9 + 1];

 cout << str << endl;

 return 0;
}

 


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

 

 \
 

 

可以看到正是25行的地方導致內存洩露的

 Code沒來得及細看,能用就是了^_^,方便就行,枉自猜測一下原理----------重載了new和delete,對他倆進行一個計數,並記下行數,兩個不為偶數,則就是代表已經出現內存洩露了


MemCheck.h:
[cpp] 
#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 

#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:
[cpp] 
#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); 

#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);
}

那哥們的測試工程,挺不錯的,有3種情況:

[cpp]
#include "stdafx.h"  
#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; 
    /**//*delete r;*/ 
    vector<int> v; 
    v.push_back(1); 
    Foo s("goodbye"); 

 
int main()  

    TRACE_OFF(); 
    MEM_ON(); 
    Test(); 
    Test2(); 
    Test3(); 
    MEM_OFF(); 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved