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

    Windows平台下的内存泄露

    使用CRTDBG

    #ifdef _DEBUG
    #define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__)
    #else
    #define DEBUG_CLIENTBLOCK
    #endif
    #define _CRTDBG_MAP_ALLOC
    #include <crtdbg.h>
    #ifdef _DEBUG
    #define new DEBUG_CLIENTBLOCK
    
    int main()
    {
    	char * p = new char[10];
    	_CrtMemDumpAllObjectsSince(nullptr); // or _CrtDumpMemoryLeaks();
    	return 0;
    }

    F5Debug输出内容为:

    Dumping objects ->
    d:\dev\csharptest\cpptest\main.cpp(262) : {236} client block at 0x00265C78, subtype 0, 10 bytes long.
     Data: <          > CD CD CD CD CD CD CD CD CD CD
    Object dump complete.

    从上面的宏可以看出来,将new重新宏定义为 new( _CLIENT_BLOCK, __FILE__, __LINE__)这样就可以定位到出现泄露的分配代码行。

    如果没有macro new则只是打印出有多少的内存泄露。

    从这里我们将会详细讨论CRT Debug Heap来检查内存泄露。

    首先CRT Debug只针对与托管代码,也就是C++。

    使用CRTDGB,需要按照如下顺序引用头文件,否则将会产生失败。

    #define _CRTDBG_MAP_ALLOC
    #include <stdlib.h>
    #include <crtdbg.h>
    宏_CRTDBG_MAP_ALLOC的作用是编译期中使用了crtdbg.h的_malloc_dbg 与 free来代替原有的malloc与free,如果你不define这个宏,你将需要将使用new的地方显示调用_malloc_dbg函数。这样也说明只能在_DEBUG宏下使用这个已经转义的malloc与free。如果是release,则使用原有的malloc与free函数。由于crtdbg.h对_malloc_dbg进行重新定义,记录的分配内存的细节,大少,代码文件以及对应的行数。

    void *_malloc_dbg(
       size_t size,
       int blockType,
       const char *filename,
       int linenumber 
    );
    
    通过函数的定义,size是由于new提供的(原有的new也是传递字节数给原有的malloc函数),后面的_CLIENT_BLOCK, __FILE__, __LINE__分别赋值于blockType, filename, linenumber。
    _CrtDumpMemoryLeaks();

    该函数将内存泄露信息打印到Debug面板中的Output窗口,同时该函数需要放置在程序退出前调用。如果程序中有很多异常处理导致可能程序退出的位置有很多,可以在程序入口出使用如下代码,它会在程序退出前自动调用_CrtDumpMemoryLeaks()函数。

    _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

    如果需要打印详细的内存分配情况可以使用Statistics函数,同时可以定位到具体调用内存分配(我没有成功实现过。。。)

    	_CrtMemState s1, s2, s3;
    	char * _p = nullptr;
    	_CrtMemCheckpoint(&s1);
    	GetMemory(_p, 10);
    	_CrtMemCheckpoint(&s2);
    	if (_CrtMemDifference(&s3, &s1, &s2))
    		_CrtMemDumpStatistics(&s3);
    	
    建立3个信息对象,然后在分配内存操作的前后通过调用_CrtMemCheckpoint捕抓信息,接着使用_CrtMemDifference对比两者信息然后通过_CrtMemDumpStatistics打印信息。

    使用Visual Leak Detector

    下载visual leak detector并且安装

    添加环境变量VLD并且在项目的头文件添加$(VLD)\include,在link搜索库中添加$(VLD)\lib\Win$(PlatformArchiteture)\

    编译代码通过DEBUG运行程序,内存泄露信息将出现在DEBUGpanel的Output窗口中。

    ---------- Block 1 at 0x003B5328: 10 bytes ----------
      Call Stack:
        d:\dev\csharptest\cpptest\main.cpp (121): cpptest.exe!GetMemory + 0x9 bytes
        d:\dev\csharptest\cpptest\main.cpp (262): cpptest.exe!main + 0xB bytes
        f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (555): cpptest.exe!__tmainCRTStartup + 0x19 bytes
        f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (371): cpptest.exe!mainCRTStartup
        0x75B93677 (File and line number not available): kernel32.dll!BaseThreadInitThunk + 0x12 bytes
        0x77069F42 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x63 bytes
        0x77069F15 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x36 bytes
      Data:
        CD CD CD CD    CD CD CD CD    CD CD                          ........ ........
    通过上面可以看到使用vld的好处时使用简单,就是安装一个库,同时在代码中引用头文件而已,可以通过宏预编译来控制是否进行内存泄露检查。

    Linux平台下内存泄露

    待补
















  • 相关阅读:
    Java如何让线程池满后再存放队列
    Java如何让线程池满后再存放队列
    Hystrix 中线程池隔离与信号量隔离区别
    微服务中服务间feign调用header传参
    JVM 垃圾收集器
    java对象引用与垃圾收集器回收算法
    JVM 中 java 对象布局
    类加载器与双亲委派机制
    sql 查询本周周一与周日时间
    VUE组件循环引用
  • 原文地址:https://www.cnblogs.com/rogerroddick/p/2846705.html
Copyright © 2011-2022 走看看