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次申请堆空间时候设置断点 .
这样就可以看到函数调用栈,从而帮助我们更加精确的定位程序泄露的位置.
C++ 海量代码 排查内存/GDI泄漏历程的更多相关文章
- GDI泄漏排查经验零散总结
1.GDI对象以及释放方法: GDI对象 产生方法 销毁方法 位图(HBITMAP) CreateBitmap,CreateBitmapIndirect, CreateCompatibleBitmap ...
- APP排查内存泄漏最简单和直观的方法
内存泄漏无疑会严重影响用户体验,一些本应该废弃的资源和对象无法被释放,导致手机内存的浪费,app使用的卡顿,那么如何排查内存泄漏呢? 当然,首先我们有google的官方文档可以参考,大部分博客 ...
- uilib库gdi句柄泄漏bug修复,duilib防止gdi泄漏的小提醒
转载请说明原出处,谢谢~~ 今天下午群友的网友让我帮忙看一下的duilib程序的问题,程序中包含了List控件,会定时清除所有子项目然后重新添加.但是程序运行一段时间后会自己崩溃!我编译了源码运行后在 ...
- GDI 泄漏检测方法
方法一 1.打开电脑的[任务管理器],选择[进程]页,点击菜单项的[查看]项,选择[选择列]: 2.勾选[GDI对象(J)]即可. 3.此时,用户就可以在进程中看到每个进程对应的GDI对象,每个进程的 ...
- 解密native代码的内存使用
前言 无论是从资源使用的角度,还是从发现内存泄漏问题的角度来看,在性能测试或者系统的稳定性测试中,内存的使用情况是一个很重要的监控点.为保证项目的质量前移,输入法内核测试小组的同学分配到了一个新的任务 ...
- Pythontutor:可视化代码在内存的执行过程
http://www.pythontutor.com/visualize.html今天去问开发一个Python浅拷贝的问题,开发给了一个神器,可以可视化代码在内存的执行过程,一看即懂,太NB了!~真是 ...
- c++ 汇编代码看内存分配
汇编代码看内存分配 (1). 程序运行时分为存储区域分为 存储区域 存储内容 extra 代码区 存放代码指令,包括除字符串常量的字面值 静态存储区 存放静态变量和全局变量 执行main之前就分配好了 ...
- [android网络有效性检测] NetworkMonitor代码造成内存泄漏
造成内存泄漏的log如下: E StrictMode: A resource was acquired at attached stack trace but never released. See ...
- 记一次使用windbg排查内存泄漏的过程
一.背景 近期有一个项目在运行当中出现一些问题,程序顺利启动,但是观察一阵子后发现内存使用总量在很缓慢地升高, 虽然偶尔还会往下降一些,但是总体还是不断上升:内存运行6个小时候从33M上升到80M: ...
随机推荐
- Jmeter系列(8)- test plam测试计划参数详解
如果你想从头学习Jmeter,可以看看这个系列的文章哦 https://www.cnblogs.com/poloyy/category/1746599.html 前言 先了解下测试计划的作用:http ...
- spark系列-7、spark调优
官网说明:http://spark.apache.org/docs/2.1.1/tuning.html#data-serialization 一.JVM调优 1.1.Java虚拟机垃圾回收调优的背景 ...
- JUC之CAS
CAS(全称为CompareAndSwap,也有说是CompareAndSet,都差不多)是一条CPU并发原语,它的功能是判断内存某个位置的值是否为预期值,如果是则更改为新的值,判断预期值和更改新值的 ...
- LeetCode--Array--Container With Most Water (Medium)
11. Container With Most Water (Medium)# Given n non-negative integers a1, a2, ..., an , where each r ...
- 自己动手写RPC
接下来2个月 给自己定个目标 年前 自己动手做个RPC 框架 暂时技术选型 是 dotcore + netty + zookeeper/Consul
- Hexo+GitHub Actions 完美打造个人博客
Hexo简介 Hexo是一款基于Node.js的静态博客框架,依赖少易于安装使用,可以方便的生成静态网页托管在GitHub和Coding上,是搭建博客的首选框架.大家可以进入hexo官网进行详细查看, ...
- MATLAB与三大变换
运行 Simulink 有三种方式: z 在 MATLAB 的命令窗口直接键入“Simulink”并回车: z 单击 MATLAB 工具条上的 Simulink 图标: z 在 MATLAB 菜单上选 ...
- Gradle 多环境URL请求设置
在开发过程中,多环境配置是经常遇到的,比如在Android开发过程中,在不同环境上请求服务器的URL是不同的,使用Gradle进行管理,是非常方便的. 首先查看工程目录结构: 使用AndroidStu ...
- vue $refs的静态绑定使用与动态绑定使用
以下实例实现的同一个操作 静态使用 this.$refs.tbhead.clearSelection(); 动态使用 area="tbhead" //可以是函数传入的参数 this ...
- Echarts关于tree树数据渲染图例最新实例
最近做项目接到新的需求,根据本身系统结构数据做一个图形化展示,要求好看易用,有交互,就说了这么多,然后就要求两天给一版瞅瞅,MMP,真把前端当神了(你倒是把待遇提到神的地位啊...) 唉,吐槽归吐槽, ...