内存泄露检查之C++实现

从事C++研发的筒子们,最挥之不去可能要算内存泄露带来的痛苦吧,在C++中,虽说其实现底层代码方面所凸显出来的性能要远高于其他类型语言,但是其由于缺乏天生的内存回收机制,从而也被业界予以诟病,那有没有办法能够监测到程序中的内存泄露问题呢,其实是有很多的办法,例如efence ,vagrind类型的工具等,但是这些工具最大的问题就是太重量级了,需要在自己的代码中安插部分调试代码,使用起来也是不很方便,基于此,本人通过学习前人的一些方法,稍微对new,delete进行了重载,基本上实现了检查程序中的内存泄露问题,好了,下面来看代码吧:

#include<stdio.h>
#include<map>
#include<boost/thread/mutex.hpp>
#include<boost/thread/locks.hpp>
using namespace boost;

#define MEM_CHECK_TABLESIZE 1024*1024
#define MEM_HASH_FUNC(ptr) ((reinterpret_cast<unsigned long>(ptr))%MEM_CHECK_TABLESIZE)
#define MEM_FILENAME_SIZE 1024

boost::mutex mut;
boost::mutex mem_mut;
struct allocMem_ptr_t
{
    allocMem_ptr_t()
    {
        bzero(fileName,sizeof(fileName));
        size = 0;
        line = 0;
        next = NULL;
    }
    char fileName[MEM_FILENAME_SIZE];
    int size;
    int line;
    allocMem_ptr_t* next;
};

struct allocMem_ptr_t* allocMem_list[MEM_CHECK_TABLESIZE];
int tableSize = 0;

struct memLeak_ptr_t
{
    memLeak_ptr_t()
    {
        bzero(fileName,sizeof(fileName));
        size = 0;
    }
    char fileName[MEM_FILENAME_SIZE];
    int size;
};
std::map<int,memLeak_ptr_t> memLeak_map;
void memCheck()
{
    size_t index = 0;
    mem_mut.lock();
    for(int i=0;i<MEM_CHECK_TABLESIZE;i++)
    {
        allocMem_ptr_t* alloc = allocMem_list[i];
        if(NULL == alloc) continue;
        while(alloc)
        {
            memLeak_ptr_t memLeak;
            sprintf(memLeak.fileName,"%s:%d",alloc->fileName,alloc->line);
            memLeak.size = alloc->size;
            memLeak_map.insert(std::make_pair(index,memLeak));
            alloc = alloc->next;
            index++;
        }
    }
    mem_mut.unlock();
    std::map<std::string,int> leakCount;
    for(int i =0;i<memLeak_map.size();i++)
        leakCount[memLeak_map[i].fileName] += memLeak_map[i].size;
    typedef std::map<std::string,int>::iterator leakCount_iter;
    for(leakCount_iter iter = leakCount.begin();iter != leakCount.end();++iter)
    {
        printf("%s LEAK MEMORY SIZE:%d\n",iter->first.c_str(),iter->second);
    }
}
void* operator new(size_t size,const char* file,int line)
{
    size_t siz = size + sizeof(allocMem_ptr_t);
    allocMem_ptr_t* ptr = (allocMem_ptr_t*)::malloc(siz);
    if(NULL == ptr) abort();
    void* p = (char*)ptr + sizeof(allocMem_ptr_t);
    strncpy(ptr->fileName,file,MEM_FILENAME_SIZE-1);
    ptr->size = size;
    ptr->line = line;

    mem_mut.lock();
    size_t index = MEM_HASH_FUNC(p);
    ptr->next = allocMem_list[index];
    allocMem_list[index] = ptr;
    ++tableSize;
    mem_mut.unlock();
    return p;
}

void* operator new[](size_t size,const char* file,int line)
{
    return operator new(size,file,line);
}

void operator delete(void* ptr)
{
    if(NULL == ptr) return;
    allocMem_ptr_t* pre = NULL;
    size_t index = MEM_HASH_FUNC(ptr);
    mem_mut.lock();
    allocMem_ptr_t* pointer = allocMem_list[index];
    while(pointer)
    {
        if((char*)pointer + sizeof(allocMem_ptr_t) == ptr)
        {
            if(NULL == pre)
                allocMem_list[index] = pointer->next;
            else
                pre->next = pointer->next;
            --tableSize;
            break;
        }
        pre = pointer;
        pointer = pointer->next;
    }
    mem_mut.unlock();
    free(pointer);
}

void operator delete[](void* pointer)
{
    operator delete(pointer);
}

void operator delete(void* pointer,const char* file,int line)
{
    operator delete(pointer);
}
void operator delete[](void* pointer,const char* file,int line)
{
    operator delete(pointer);
}
#ifndef __MEM_CHECK__H
#define __MEM_CHECK__H
#include<stdio.h>
#include<string>
#define MEM_CHECK memCheck()
void memCheck();
void* operator new(size_t size,const char* file,int line);
void* operator new[](size_t size,const char* file,int line);

void operator delete(void* pointer,const char* file,int line);
void operator delete[](void* pointer,const char* file,int line);

#define  MEM_ALLOC new(__FILE__,__LINE__)
#define  MEM_DELETE delete
#endif

测试程序:

#include "MemCheck.h"


struct point
{
    point()
    {
        posX = 0;
        posY = 0;
    }
    int posX;
    int posY;
};

int main(int argc,char* argv[])
{
    int* pointer = MEM_ALLOC int();
    double* doub = MEM_ALLOC double();
    std::string* str = MEM_ALLOC std::string();
    point* po = MEM_ALLOC point();
    MEM_DELETE pointer;
    MEM_DELETE po;
    MEM_CHECK;
    return 0;
}

测试结果:

Test.cpp:18 LEAK MEMORY SIZE:8
Test.cpp:19 LEAK MEMORY SIZE:4

总结

       本篇博文主要是通过封装new、delete操作,实现了一个简单版的检查内存泄露工具,原理很简单:通过一个简单的hash表来存放相关的内存分配信息,这个hash表会随着内存分配操作而动态的调整,这个实现思路其实还是有部分的问题,但总体上来将还是应用于实际的项目,好好地体会吧,有机会的话,我们可以使用redis来改写下这个功能,好了,本篇博文到此结束。

如果需要,请注明转载,多谢
 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值