• C++ 海量代码 排查内存/GDI泄漏历程


    排查分两大部分:

    1.代码静态分析,通过Code Review查找不合规范的代码点;

    2.运行目标软件,结合内存监控工具,分析目标软件的代码,定位内存泄漏点。

    目前能找到的代码静态分析软件:Coverity代码静态检查工具(Synosys公司的)、Fortify SCA(擅长JAVA,C++也能分析)、PVS-Studo、PC-lint。

    内存监控工具:

    Bounds check、Deleaker、CRTDBG(VS自带的,编译DEBUG版本,内存泄漏时会在Debug窗口中有打印信息)。

    Deleaker:

                     使用简单,功能强大,除了内存泄漏还可以检查GDI泄漏,安装包自带VS插件,同时也支持其他IDE。

                下载地址:https://www.deleaker.com/

                     免费试用14天,年费$299

                     安装步骤:按照默认步骤安装。

                     使用方法:安装完后,VS中会出现一个Deleaker的菜单项,点击打开Deleaker的界面,勾选Enable后,运行调试,则Deleaker也会进入分析状态,结束调试则会完成分析结果。

           Deleaker分析代码有两种模式,一种是托管代码,一种是非托管代码,根据实际情况选择。

                     Deleaker界面如下,常用按钮已标记出来:   

                     Unmanaged Code Profiling Mode  :非托管代码模式

                     .Net Profiling Mode :托管代码模式

                     Allocation Types:可以配置要分析的缺陷类型,比如内存、GDI。

                     Take Snapshot是用来进行暂存内存快照的,和VS2017诊断工具差不多。

                     Module可以按照模块筛选分析结果,Leak Type可以按照缺陷类型筛选分析结果。

                    Options项是一些高级配置,一般使用默认配置就可以了。

                    最下方两个空白窗口分别是分析结果和调用栈信息,选中一条分析结果就可以精确定位到泄漏的代码行了。

                    

    Viual Leak detector:

    Viual Leak detector安装后,要在VS中设置相应的头文件和库路径,在Debug模式下如果要检测相应源文件的内存泄露,则加上"#include <vld.h>"即可;

    将.h文件拷贝到Visual C++的默认include目录下,将.lib文件拷贝到Visual C++的默认lib目录下,便安装完成了。(因为版本问题,如果使用windows 2000或者以前的版本,需要将dbghelp.dll拷贝到你的程序的运行目录下,或其他可以引用到的目录)。接下来需要将其加入到自己的代码中。方式很简单,只要在包含入口函数的.cpp文件中包含vld.h就可以。如果这个cpp文件包含了stdafx.h,则将包含vld.h的语句放在stdafx.h的包含语句之后,否则放在最前面。

    在检测内存泄露,可以在VS的输出窗口查看输出信息。

    CRTDbg:

          工具局限性:

                           1)对于调试非MFC程序,不能打印文件名和行号。对于一个比较大的程序,没有这些信息,解决问题将变得十分困难。

                           2)由于Debug Function实现在MS C-RuntimeLibrary中,所以它只能检测到堆内存的泄漏,而且只限于malloc,realloc或strdup等分配的内存,而那些系统资 源,比如HANDLE,GDI                                         Object,或是不通过C-Runtime Library分配的内存,比如VARIANT,BSTR的泄漏,它是无法检测到的,这是这种检测法的一个重大的局限性。

                           3)为了能记录内存块是在哪里 分配的,源代码必须相应的配合,这在调试一些老的程序非常麻烦,毕竟修改源代码不是一件省心的事,这是这种检测法的另一个局限性。

          工具使用:

                           没有工具的情况下,使用crtdbg.h中的api也是可以的,但是有之前说的两个局限性。

                           在MFC中可以看到在程序退出的时候,输出框内结尾部分输出内存泄露,并且点击可以跳转到内存泄露的代码处。

                           A) _CrtSetDbgFlag函数,这个函数用于控制debug模式下堆管理的分配行为;(函数详细信息参考:http://msdn.microsoft.com/zh-cn/library/5at7yxcs.aspx)

                               在main函数开始处添加该函数,则如果出现内存泄露Debug结束后,输出框将输出打印信息。

                                    _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);  

                                    //_CRTDBG_REPORT_FLAG:表示获取当前的标示位    //_CRTDBG_LEAK_CHECK_DF:表示检测内存泄露  

                           B) 显示内存泄露所在的文件以及行

                                能够知道有内存泄露是不够的,更需要的信息是哪里内存泄露了?

                                我们可以在每个源文件的开头定义写这样一条宏定义:

                                #define new   new(_NORMAL_BLOCK, __FILE__, __LINE__)       //根据__FILE___和__LINE__能够确定文件和行  

                           C) 显示内存泄露处的堆栈,(函数详细信息参考:http://technet.microsoft.com/zh-cn/library/aa246759)

                                long _CrtSetBreakAlloc( long lBreakAlloc );  //lBreakAlloc,在申请的堆区序号为lBreakAlloc处设置一个断点  

                                此函数在指定的申请堆区空间次序处(即lBreakAlloc)设置断点;这个函数结合"A)"中提到的{150},比如使用方法:

                                _CrtSetBreakAlloc(150); //则在第150次申请堆空间时候设置断点  .

                                这样就可以看到函数调用栈,从而帮助我们更加精确的定位程序泄露的位置.

  • 相关阅读:
    Spring MVC 复习笔记03
    Spring MVC 复习笔记02
    CSS之选择器
    Filedset
    Label标签
    Table标签
    列表标签
    CSS之img标签
    CSS之a标签锚点
    CSS之checkbox&radio&textarea&select
  • 原文地址:https://www.cnblogs.com/lmst-ytt/p/12875328.html
Copyright © 2020-2023  润新知