内存泄漏检查

关于内存泄漏的检查网上有很多的例子和代码,其基本的方法都是用宏,替换掉内存分配以及释放的函数。但是现在网上很多的例子中没有一个是适合我们公司的需求的。
具体的对内存泄漏检查有如下要求:
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 拷贝到与被检查内存泄漏的进程所在的目录下面

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

 

下载地址

转载于:https://www.cnblogs.com/russinovich/archive/2011/08/12/2135625.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目前有一款常用的内存泄漏检测工具是Visual Leak Detector(VLD)。 VLD是一款免费的内存泄漏检测工具,适用于Visual C环境。它能够为每个泄漏的块提供完整的堆栈跟踪信息,包括源文件和行号。同时,VLD可以检测大多数类型的进程内内存泄漏,包括基于COM的泄漏和纯Win32基于堆的泄漏。此外,VLD还支持设置过滤指定的模块,不参与内存泄漏检查,并提供泄漏块的完整数据转储。你可以将泄漏报告保存到文件或发送到调试器,并可以设置不同的详细级别。VLD是一个已经打包的库,使用时无需编译其源代码,只需引入头文件即可。它的源代码使用GNU许可发布,并有详尽的文档和注释,适合想深入了解堆内存管理的读者使用。 [2] 另外,还有一种内存泄漏检测工具是QT内置的功能。当一个QObject正在接受事件队列时,如果中途被销毁,可能会导致问题。为了避免这种情况,推荐使用QObject的deleteLater()函数来删除QObject对象。这个函数会发送一个删除事件到事件系统,让所有事件都处理完之后再清除内存。而且,即使多次调用deleteLater()函数也不会出现问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Qt / MSVC 中使用内存泄露检测工具 VLD(Visual Leak Detector)](https://blog.csdn.net/weixin_41863029/article/details/128482295)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Qt内存泄漏总结(包括检测工具)](https://blog.csdn.net/a844651990/article/details/78814076)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值