zoukankan      html  css  js  c++  java
  • 内存泄漏检查

    关于内存泄漏的检查网上有很多的例子和代码,其基本的方法都是用宏,替换掉内存分配以及释放的函数。但是现在网上很多的例子中没有一个是适合我们公司的需求的。
    具体的对内存泄漏检查有如下要求:
    1. 内存泄漏检查的代码尽可能少的占用CPU及内存
    2. 尽可能的不影响原程序


    因为,我们的服务器程序有泄漏而且是特殊情况下会泄漏,平时很难模拟出来。
    对于这种情况下的内存泄漏我以前的做法如下:
    1.  用写文件的方法记录所有的内存分配以及释放的操作
    2.  再写一个工具去分析所有的记录,从中找出泄漏的代码
    这样做需要大量的硬盘空间,不过,这个无所谓了现在硬盘很便宜!
     

    不过需要考虑到服务器程序当中包含了exe以及多个dll,为了通用,内存泄漏检查分为下面几个部分:
    1. IMemLeak.h IMemLeak.cpp  加入每一个模块当中
    2. MemLeakLog.dll  统一记录所有的内存操作,将其记录到文件当中
    3. MemCheckTool.exe  分析工具

     


    //IMemLeak.h
    #ifndef _YG_MEMDBG_H_
    #define _YG_MEMDBG_H_
    
    #include <cstdlib>
    
    //Redefines
    #define malloc(size) mallocb(size, __FILE__, __LINE__)
    #define free(memblock) freeb(memblock, __FILE__, __LINE__)
    #define realloc(memblock, size) reallocb(memblock, size, __FILE__, __LINE__)
    #define calloc(num, size) callocb(num, size, __FILE__, __LINE__)
    
    //Redefined functions
    void * mallocb(size_t size, const char *pszFile, int nLine);
    void freeb(void *memblock, const char *pszFile, int nLine);
    void * reallocb(void *memblock, size_t size, const char *pszFile, int nLine);
    void * callocb(size_t num, size_t size, const char *pszFile, int nLine);
    
    //For C++
    void * operator new(size_t size, const char *pszFile, int nLine);
    void * operator new[](size_t size, const char *pszFile, int nLine);
    
    void operator delete(void *pvMem) throw();
    void operator delete[](void *pvMem) throw();
    
    void pre_delete(const char *pszFile, int nLine);
    
    //Redefine new and delete
    #define new     new(__FILE__, __LINE__)
    #define delete    pre_delete(__FILE__, __LINE__),delete
    
    #endif

    //IMemLeak.cpp
    #include <stdio.h>
    #include <tchar.h>
    #include <stdlib.h>
    #include <malloc.h>
    #include <Windows.h>
    #include <cstdlib>
    
    enum EOperateType
    {
        Type_Malloc,
        Type_Calloc,
        Type_Realloc,
        Type_New,
        Type_New_Array,
        Type_Free,
        Type_Delete,
        Type_Delete_Array
    };
    
    typedef void (__stdcall * pFun_MemLeakLog)(LPCSTR PLog);
    
    pFun_MemLeakLog MemLeakLog = NULL;
    
    void CheckMemLeakLogDLL()
    {
        if (MemLeakLog == NULL)
        {
            HINSTANCE  hinstLib = LoadLibrary(_T("MemLeakLog.dll"));
            if (hinstLib != NULL)
            {
                MemLeakLog = (pFun_MemLeakLog)GetProcAddress(hinstLib, "MemLeakLog");
            }
        }
    }
    
    void Log(EOperateType type, void * pmem, size_t size, int nLine, const char* pszFile)
    {
        CheckMemLeakLogDLL();
    
        char temp[1024];
        if (MemLeakLog != NULL)
        {
            memset(temp, 0, 1024);
            sprintf_s(temp, 1024, "%d-%p-%d-%d [%s]\n", type, pmem, size, nLine, pszFile);
            MemLeakLog(temp);
        }
    }
    
    void * mallocb(size_t size, const char *pszFile, int nLine)
    {
        void * pRet = malloc(size);
        Log(Type_Malloc, pRet, size, nLine, pszFile);
        return pRet;
    }
    
    void * callocb(size_t num, size_t size, const char *pszFile, int nLine)
    {
        void * pRet = calloc(num, size);
        Log(Type_Calloc, pRet, size, nLine, pszFile);
        return pRet;
    }
    
    void freeb(void *memblock, const char *pszFile, int nLine)
    {
        if (memblock)
        {
            Log(Type_Free, memblock, 0, 0, "NULL");
        }
    
        free(memblock);
    }
    
    void * reallocb(void *memblock, size_t size, const char *pszFile, int nLine)
    {
        void * pRet;
        pRet = realloc(memblock, size);
    
        Log(Type_Free,    memblock, size, nLine, pszFile);
        Log(Type_Realloc, pRet, size, nLine, pszFile);
        return pRet;
    }
    
    void * operator new(size_t size, const char *pszFile, int nLine)
    {
        void * pRet = malloc(size);
    
        Log(Type_New, pRet, size, nLine, pszFile);
        return pRet;
    }
    
    void * operator new[](size_t size, const char *pszFile, int nLine)
    {
        void * pRet = malloc(size);
    
        Log(Type_New_Array, pRet, size, nLine, pszFile);
        return pRet;
    }
    
    //#include <new>
    
    void operator delete(void *memblock) throw ()
    {
        if (memblock)
        {
            Log(Type_Delete, memblock, 0, 0, "NULL");
        }
    
        free(memblock);
    }
    
    void operator delete[](void *memblock) throw()
    {
        if (memblock)
        {
            Log(Type_Delete_Array, memblock, 0, 0, "NULL");
        }
    
        free(memblock);
    }
    
    void pre_delete(const char *pszFile, int nLine)
    {
        
    }


    MEM_1

    MEM_2

    注意:
    a. 输出的目录我是写死了,在D:\MemLeak_Log
    b. 在被检查工程里面请增加/FC选项。Project->Properties->Configuration->C/C++->Advanced->Use Full Path Yes(/FC)
    c. MemLeakLog.dll 拷贝到与被检查内存泄漏的进程所在的目录下面

    我附带上一个例子,大家一看就明白了。

     

    下载地址

  • 相关阅读:
    Redis数据模型
    Redis集群使用的一些命令(持续更新)
    Redis简单集群搭建
    观察者模式
    抽象工厂模式
    简单工厂模式及其简单Java案例代码实现
    工厂方法模式及简单Java案例代码实现
    Java中的双重检查锁(double checked locking)
    BayaiM__MYSQL千万级数据量的优化方法积累__初级菜鸟
    BayaiM__Linux安装MySQL的两种方法
  • 原文地址:https://www.cnblogs.com/russinovich/p/2135625.html
Copyright © 2011-2022 走看看