排查分两大部分:

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次申请堆空间时候设置断点  .

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

C++ 海量代码 排查内存/GDI泄漏历程的更多相关文章

  1. GDI泄漏排查经验零散总结

    1.GDI对象以及释放方法: GDI对象 产生方法 销毁方法 位图(HBITMAP) CreateBitmap,CreateBitmapIndirect, CreateCompatibleBitmap ...

  2. APP排查内存泄漏最简单和直观的方法

        内存泄漏无疑会严重影响用户体验,一些本应该废弃的资源和对象无法被释放,导致手机内存的浪费,app使用的卡顿,那么如何排查内存泄漏呢? 当然,首先我们有google的官方文档可以参考,大部分博客 ...

  3. uilib库gdi句柄泄漏bug修复,duilib防止gdi泄漏的小提醒

    转载请说明原出处,谢谢~~ 今天下午群友的网友让我帮忙看一下的duilib程序的问题,程序中包含了List控件,会定时清除所有子项目然后重新添加.但是程序运行一段时间后会自己崩溃!我编译了源码运行后在 ...

  4. GDI 泄漏检测方法

    方法一 1.打开电脑的[任务管理器],选择[进程]页,点击菜单项的[查看]项,选择[选择列]: 2.勾选[GDI对象(J)]即可. 3.此时,用户就可以在进程中看到每个进程对应的GDI对象,每个进程的 ...

  5. 解密native代码的内存使用

    前言 无论是从资源使用的角度,还是从发现内存泄漏问题的角度来看,在性能测试或者系统的稳定性测试中,内存的使用情况是一个很重要的监控点.为保证项目的质量前移,输入法内核测试小组的同学分配到了一个新的任务 ...

  6. Pythontutor:可视化代码在内存的执行过程

    http://www.pythontutor.com/visualize.html今天去问开发一个Python浅拷贝的问题,开发给了一个神器,可以可视化代码在内存的执行过程,一看即懂,太NB了!~真是 ...

  7. c++ 汇编代码看内存分配

    汇编代码看内存分配 (1). 程序运行时分为存储区域分为 存储区域 存储内容 extra 代码区 存放代码指令,包括除字符串常量的字面值 静态存储区 存放静态变量和全局变量 执行main之前就分配好了 ...

  8. [android网络有效性检测] NetworkMonitor代码造成内存泄漏

    造成内存泄漏的log如下: E StrictMode: A resource was acquired at attached stack trace but never released. See ...

  9. 记一次使用windbg排查内存泄漏的过程

    一.背景 近期有一个项目在运行当中出现一些问题,程序顺利启动,但是观察一阵子后发现内存使用总量在很缓慢地升高, 虽然偶尔还会往下降一些,但是总体还是不断上升:内存运行6个小时候从33M上升到80M: ...

随机推荐

  1. muduo网络库源码学习————Timestamp.cc

    今天开始学习陈硕先生的muduo网络库,moduo网络库得到很多好评,陈硕先生自己也说核心代码不超过5000行,所以我觉得有必要拿过来好好学习下,学习的时候在源码上面添加一些自己的注释,方便日后理解, ...

  2. Linux安装Git-两种方式详细教程)

    一.Git介绍 Git --- The stupid content tracker, 傻瓜内容跟踪器.Linus Torvalds 是这样给我们介绍 Git 的. Git 是用于 Linux内核开发 ...

  3. Hadoop入门学习笔记-第三天(Yarn高可用集群配置及计算案例)

    什么是mapreduce 首先让我们来重温一下 hadoop 的四大组件:HDFS:分布式存储系统MapReduce:分布式计算系统YARN: hadoop 的资源调度系统Common: 以上三大组件 ...

  4. E. Count The Blocks(找数学规律)

    \(\color{Red}{先说一下自己的歪解(找规律)}\) \(n=1是答案是10\) \(n=2时答案是180\) \(n=3时模拟一下,很容易发现答案是2610\ \ 180\ \ 10\) ...

  5. Polycarp and Div 3 CodeForces - 1005D

    这个题目其实很简单,有很多的方法写,然后我还是不会写,感觉自己好菜, 我开始想的是dp,但是不知道怎么dp,看了网上题解,豁然开朗 dp[i] 表示前面i个数满足条件的数有多少,f[s]表示前缀和为s ...

  6. Spring官网阅读(十四)Spring中的BeanWrapper及类型转换

    文章目录 接口定义 继承关系 接口功能 1.PropertyEditorRegistry(属性编辑器注册器) 接口定义 PropertyEditor 概念 Spring中对PropertyEditor ...

  7. NEON中的L可以避免溢出

    在做加法时,比如两个255x255的数值相加,那么正确结果将是130050,对一个最大值为65565的unsigned short是会溢出的,但是如果使用L命令时,则不会产生溢出.这说明L命令,不是先 ...

  8. Altium Designer PCB封装bug,元件焊盘位置偏移解决方法

    1.问题描述:在拖动几个电阻位置时,意外发现Altium designer20版本软件的一个bug——0805的电阻两焊盘位置发生了偏移,如下图所示. 2.解决办法: ①选中焊盘偏移的封装,右键剪切掉 ...

  9. Redis学习笔记(八) RDB持久化

    Redis是内存数据库,它将自己的数据库状态存储在内存里面,所以如果不想办法将存储在内存中的数据库状态保存到磁盘,那么服务器 进程一旦退出,服务器中的数据库状态也会消失不见. 为了解决这个问题,Red ...

  10. 向大家介绍我的新书:《基于股票大数据分析的Python入门实战》

    我在公司里做了一段时间Python数据分析和机器学习的工作后,就尝试着写一本Python数据分析方面的书.正好去年有段时间股票题材比较火,就在清华出版社夏老师指导下构思了这本书.在这段特殊时期内,夏老 ...