C++内存泄露的检测(三)

本文介绍了一种通过重载new和delete操作符实现的简单C++内存泄漏检测方法。该方法能够有效跟踪内存分配和释放情况,帮助开发者定位内存泄漏问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 一 简单的对内存的分配和释放跟踪,并将结果输出到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 (!&& 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 *= 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 *= NULL; // better for read
        i = new int(0);    
        
int *&= 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->= 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();
}
 ///:~

四 测试结果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值