怎么排查这些内存泄漏 (怎么排查这些病毒)

本文目录导航:

怎么排查这些内存泄漏

最原始的内存泄露测试重复多次操作关键的可疑的路径,从内存监控工具中观察内存曲线,是否存在不断上升的趋势且不会在程序返回时明显回落。

这种方式可以发现最基本,也是最明显的内存泄露问题,对用户价值最大,操作难度小,性价比极高。

MAT内存分析工具2.1 MAT分析heap的总内存占用大小来初步判断是否存在泄露在Devices 中,点击要监控的程序。

点击Devices视图界面中最上方一排图标中的“Update Heap”点击Heap视图点击Heap视图中的“Cause GC”按钮到此为止需检测的进程就可以被监视。

Heap视图中部有一个Type叫做data object,即数据对象,也就是我们的程序中大量存在的类类型的对象。

在data object一行中有一列是“Total Size”,其值就是当前进程中所有Java数据对象的内存总量,一般情况下,这个值的大小决定了是否会有内存泄漏。

可以这样判断:进入某应用,不断的操作该应用,同时注意观察data object的Total Size值,正常情况下Total Size值都会稳定在一个有限的范围内,也就是说由于程序中的的代码良好,没有造成对象不被垃圾回收的情况。

所以说虽然我们不断的操作会不断的生成很多对象,而在虚拟机不断的进行GC的过程中,这些对象都被回收了,内存占用量会会落到一个稳定的水平;反之如果代码中存在没有释放对象引用的情况,则data object的Total Size值在每次GC后不会有明显的回落。

随着操作次数的增多Total Size的值会越来越大,直到到达一个上限后导致进程被杀掉。

2.2 MAT分析hprof来定位内存泄露的原因所在。

这是出现内存泄露后使用MAT进行问题定位的有效手段。

A)Dump出内存泄露当时的内存镜像hprof,分析怀疑泄露的类:B)分析持有此类对象引用的外部对象C)分析这些持有引用的对象的GC路径D)逐个分析每个对象的GC路径是否正常从这个路径可以看出是一个antiRadiationUtil工具类对象持有了MainActivity的引用导致MainActivity无法释放。

此时就要进入代码分析此时antiRadiationUtil的引用持有是否合理(如果antiRadiationUtil持有了MainActivity的context导致节目退出后MainActivity无法销毁,那一般都属于内存泄露了)。

2.3 MAT对比操作前后的hprof来定位内存泄露的根因所在。

为查找内存泄漏,通常需要两个 Dump结果作对比,打开 Navigator History面板,将两个表的 Histogram结果都添加到 Compare Basket中去A) 第一个HPROF 文件(usingFile > Open Heap Dump ).B)打开Histogram view.C)在NavigationHistory view里 (如果看不到就从Window >show view>MAT- Navigation History ), 右击histogram然后选择Add to Compare Basket .D)打开第二个HPROF 文件然后重做步骤2和3.E)切换到Compare Basket view, 然后点击Compare the Results (视图右上角的红色”!”图标)。

F)分析对比结果可以看出两个hprof的数据对象对比结果。

通过这种方式可以快速定位到操作前后所持有的对象增量,从而进一步定位出当前操作导致内存泄露的具体原因是泄露了什么数据对象。

注意:如果是用 MAT Eclipse 插件获取的 Dump文件,不需要经过转换则可在MAT中打开,Adt会自动进行转换。

而手机SDk Dump 出的文件要经过转换才能被 MAT识别,Android SDK提供了这个工具 hprof-conv (位于 sdk/tools下)首先,要通过控制台进入到你的 android sdk tools 目录下执行以下命令:./hprof-conv 例如 hprof-conv 此时才能将放在eclipse的MAT中打开。

手机管家内存泄露每日监控方案目前手机管家的内存泄露每日监控会自动运行并输出是否存在疑似泄露的报告邮件,不论泄露对象的大小。

这其中涉及的核心技术主要是AspectJ,MLD自研工具(原理是虚引用)和UIAutomator。

3.1 AspectJ插桩监控代码手机管家目前使用一个ant脚本加入MLD的监控代码,并通过AspectJ的语法实现插桩。

使用AspectJ的原因是可以灵活分离出项目源码与监控代码,通过不同的编译脚本打包出不同用途的安装测试包:如果测试包是经过Aspect插桩了MLD监控代码的话,那么运行完毕后会输出指定格式的日志文件,作为后续分析工作的数据基础。

3.2 MLD实现监控核心逻辑这是手机管家内的一个工具工程,正式打包不会打入,BVT等每日监控测试包可以打入。

打入后可以通过诸如addObject接口(通过反射去检查是否含有该工具并调用)来加入需要监控的检测对象,这个工具会自动在指定时机(如退出管家)去检测该对象是否发生泄漏。

这个内存泄露检测的基本原理是:虚引用主要用来跟踪对象被垃圾回收器回收的活动。

虚引用必须和引用队列(ReferenceQueue)联合使用(在虚引用函数就必须关联指定)。

当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,自动把这个虚引用加入到与之关联的引用队列中。

程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。

基于以上原理,MLD工具在调用接口addObject加入监控类型时,会为该类型对象增加一个虚引用,注意虚引用并不会影响该对象被正常回收。

因此可以在ReferenceQueue引用队列中统计未被回收的监控对象是否超过指定阀值。

利用PhantomReferences(虚引用)和ReferenceQueue(引用队列),当PhantomReferences被加入到相关联的ReferenceQueue时,则视该对象已经或处于垃圾回收器回收阶段了。

MLD监控原理核心目前手机管家已对大部分类完成内存泄露的监控,包括各种activity,service和view页面等,务求在技术上能带给用户最顺滑的产品体验。

接下来简单介绍下这个工具的判断核心。

根据虚引用监控到的内存状态,需要通过多种策略来判断是否存在内存泄露。

(1)最简单的方式就是直接在加入监控时就为该类型设定最大存在个数,举个例子,各个DAO对象理论上只能存在最多一个,因此一旦出现两个相同的DAO,那一般都是泄露了;(2)第二种情况是在页面退出程序退出时,检索gc后无法释放的对象列表,这些对象类型也会成为内存泄露的怀疑对象;(3)最后一种情况比较复杂,基本原理是根据历史操作判断对象数量的增长幅度。

根据对象的增长通过最小二乘法拟合出该对象类型的增长速度,如果超过经验值则会列入疑似泄露的对象列表。

3.3 UIAutomator完成重复操作的自动化最后一步就很简单了。

这么多反复的UI操作,让人工来点就太浪费人力了。

我们使用UIAutomator来进行自动化操作测试。

目前手机管家的每日自动化测试已覆盖各个功能的主路径,并通过配置文件的方式来灵活驱动用例的增删改查,最大限度保证了随着版本推移用例的复用价值。

至此手机管家的内存泄露测试方案介绍完毕,也欢迎各路牛人交流沟通更多更强的内存泄露工具盒方案!腾讯Bugly简介Bugly是腾讯内部产品质量监控平台的外发版本,其主要功能是App发布以后,对用户侧发生的Crash以及卡顿现象进行监控并上报,让开发同学可以第一时间了解到App的质量情况,及时机型修改。

目前腾讯内部所有的产品,均在使用其进行线上产品的崩溃监控。

怎么排查这些内存泄漏 (怎么排查这些病毒)

如何检查内存泄露问题

一、内存泄漏的检查方法-Linux和Solaris下对C和C++程序的简单的使用内存泄漏和malloc调试库。

-Debug Malloc Fence-Linux分发版中由Bruce Perens编写的malloc()调试库。

-Linux下检测内存泄漏的程序。

-Linux、Solaris和HP-UX下跟踪和分析C++程序中的内存泄漏。

-由Johan Lindh编写,是一个开放源代码C语言内存错误检测工具,主要是通过gcc的precessor来进行。

-Debugging and profiling Linux programs, aiming at programs written in C and C++-A visualization tool for the profiling>如何检查内存泄露问题

简单说明了一下没有工具的情况如何运用VC库中的工具来检查代码的内存泄漏问题。

一: 内存泄漏内存泄漏是编程中常常见到的一个问题,内存泄漏往往会一种奇怪的方式来表现出来,基本上每个程序都表现出不同的方式。

但是一般最后的结果只有两个,一个是程序当掉,一个是系统内存不足。

还有一种就是比较介于中间的结果程序不会当,但是系统的反映时间明显降低,需要定时的Reboot才会正常。

有 一个很简单的办法来检查一个程序是否有内存泄漏。

就是是用Windows的任务管理器(Task Manager)。

运行程序,然后在任务管理器里面查看 “内存使用”和”虚拟内存大小”两项,当程序请求了它所需要的内存之后,如果虚拟内存还是持续的增长的话,就说明了这个程序有内存泄漏问题。

当然如果内存泄漏的数目非常的小,用这种方法可能要过很长时间才能看的出来。

当然最简单的办法大概就是用CompuWare的BoundChecker 之类的工具来检测了,不过这些工具的价格对于个人来讲稍微有点奢侈了。

如果是已经发布的程序,检查是否有内存泄漏是又费时又费力。

所以内存泄漏应该在Code的生成过程就要时刻进行检查。

二: 原因 内存泄漏产生的原因一般是三种情况:分配完内存之后忘了回收;程序Code有问题,造成没有办法回收;某些API函数操作不正确,造成内存泄漏。

1. 内存忘记回收,这个是不应该的事情。

但是也是在代码种很常见的问题。

分配内存之后,用完之后,就一定要回收。

如果不回收,那就造成了内存的泄漏,造成内存泄漏的Code如果被经常调用的话,那内存泄漏的数目就会越来越多的。

从而影响整个系统的运行。

比如下面的代码:for (int =0;I<100;I++){Temp = new BYTE[100];}就会产生 100*100Byte的内存泄漏。

2. 在某些时候,因为代码上写的有问题,会导致某些内存想回收都收不回来,比如下面的代码:Temp1 = new BYTE[100];Temp2 = new BYTE[100];Temp2 = Temp1;这样,Temp2的内存地址就丢掉了,而且永远都找不回了,这个时候Temp2的内存空间想回收都没有办法。

3. API函 数应用不当,在Windows提供API函数里面有一些特殊的API,比如FormatMessage。

如果你给它参数中有FORMAT_MESSAGE_ALLOCATE_BUFFER,它会在函数内部New一块内存Buffer出来。

但是这个 buffer需要你调用LocalFree来释放。

如果你忘了,那就会产生内存泄漏。

三: 检查方法一 般的内存泄漏检查的确是很困难,但是也不是完全没有办法。

如果你用VC的库来写东西的话,那么很幸运的是,你已经有了很多检查内存泄漏的工具,只是你想不 想用的问题了。

Visual C++的Debug版本的C运行库(C Runtime Library)。

它已经提供好些函数来帮助你诊断你的代码和跟踪内存泄漏。

而且最方便的地方是这些函数在Release版本中完全不起任何作用,这样就不会影响你的Release版本程序的运行效率。

比如下面的例子里面,有一个明细的内存泄漏。

当然如果只有这么几行代码的话,是很容易看出有内存泄漏的。

但是想在成千上万行代码里面检查内存泄漏问题就不是那么容易了。

char * pstr = new char[5];lstrcpy(pstr,Memory leak);如 果我们在Debug版本的Code里面对堆(Heap)进行了操作,包括malloc, free, calloc, realloc, new 和 delete可以利用VC Debug运行时库中堆Debug函数来做堆的完整性和安全性检查。

比如上面的代码,lstrcpy的操作明显破坏了pstr的堆结构。

使其溢出,并破坏 了临近的数据。

那我们可以在调用lstrcpy之后的代码里面加入 _CrtCheckMemory函数。

_CrtCheckMemory函数发现前面的lstrcpy使得pstr的堆结构被破坏,会输出这样的报告:emory check error at 0xFA5 = 0x79, should be check error at 0xFA6 = 0x20, should be check error at 0xFA7 = 0x6C, should be check error at 0xFA8 = 0x65, should be : after Normal block (#41) at located at 0xFA0 is 5 bytes long. 它 告诉说 pstr的长度应该时5个Bytes,但是在5Bytes后面的几个Bytes也被非法改写了。

提醒你产生了越界操作。

_CrtCheckMemory 的返回值只有TRUE和FALSE,那么你可以用_ASSERTE()来报告出错信息。

上面的语句可以换成 _ASSERTE(_CrtCheckMemory()); 这样Debug版本的程序在运行的时候就会弹出一个警告对话框,这样就不用在运行时候一直盯着Output窗口看了。

这个时候按Retry,就可以进入源 代码调试了。

看看问题到底出在哪里。

其他类似的函数还有 _CrtDbgReport, _CrtDoForAllClientObjects, _CrtDumpMemoryLeaks,_CrtIsValidHeapPointer, _CrtIsMemoryBlock, _CrtIsValidPointer,_CrtMemCheckpoint, _CrtMemDifference, _CrtMemDumpAllObjectsSince, _CrtMemDumpStatistics, _CrtSetAllocHook, _CrtSetBreakAlloc, _CrtSetDbgFlag,_CrtSetDumpClient, _CrtSetReportFile, _CrtSetReportHook, _CrtSetReportMode这 些函数全部都可以用来在Debug版本中检查内存的使用情况。

具体怎么使用这些函数就不在这里说明了,各位可以去查查MSDN。

在这些函数中用处比较大 的,或者说使用率会比较高的函数是_CrtMemCheckpoint, 设置一个内存检查点。

这个函数会取得当前内存的运行状态。

_CrtMemDifference 检查两种内存状态的异同。

_CrtMemDumpAllObjectsSince 从程序运行开始,或者从某个内存检查点开始Dump出堆中对象的信息。

还有就是_CrtDumpMemoryLeaks当发生内存溢出的时候Dump出堆 中的内存信息。

_CrtDumpMemoryLeaks一般都在有怀疑是内存泄漏的代码后面调用。

比如下面的例子:#include <windows.h>#include <crtdbg.h>void main(){char * pstr;pstr = new char[5];_CrtDumpMemoryLeaks();}输出:Detected memory leaks! à提醒你,代码有内存泄漏 objects ->{44} normal block at 0xDB8, 5 bytes : < > CD CD CD CD CDObject dump complete.如 果你双击包含行文件名的输出行,指针将会跳到源文件中内存被分配地方的行。

当无法确定那些代码产生了内存泄漏的时候,我们就需要进行内存状态比较。

在可疑 的代码段的前后设置内存检查点,比较内存使用是否有可疑的变化。

以确定内存是否有泄漏。

为此要先定义三个_CrtMemState 对象来保存要比较的内存状态。

两个是用来比较,一个用了保存前面两个之间的区别。

_CrtMemState Sh1,Sh2,Sh_Diff;char *pstr1 = new char[100];_CrtMemCheckPoint(&Sh1); ->设置第一个内存检查点char *pstr2 = new char[100];_CrtMemCheckPoint(&Sh2); ->设置第二个内存检查点_CrtMemDifference(&Sh_Diff, &Sh1, &Sh2); ->检查变化_CrtMemDumpAllObjectsSince(&Sh_Diff); ->Dump变化如 果你的程序中使用了MFC类库,那么内存泄漏的检查方法就相当的简单了。

因为Debug版本的MFC本身就提供一部分的内存泄漏检查。

大部分的new 和delete没有配对使用而产生的内存泄漏,MFC都会产生报告。

这个主要是因为MFC重载了Debug版本的new 和delete操作符, 并且对前面提到的API函数重新进行了包装。

在MFC类库中检查内存泄漏的Class就叫 CMemoryState,它重新包装了了_CrtMemState,_CrtMemCheckPoint, _CrtMemDifference, _CrtMemDumpAllObjectsSince这些函数。

并对于其他的函数提供了Afx开头的函数,供MFC程序使用。

比如 AfxCheckMemory, AfxDumpMemoryLeaks 这些函数的基本用法同上面提到的差不多。

CMemoryState和相关的函数的定义都在Afx.h这个头文件中。

有个简单的办法可以跟踪到这些函数的声明。

在VC中找到MFC程序代码中下面的代码, 一般都在的开头部分#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif把 光标移到DEBUG_NEW上面 按F12,就可以进入Afx.h中定义这些Class和函数的代码部分。

VC中内存泄漏的常规检查办法主要是上面的两种。

当然这两种方法只是针对于Debug版本的Heap的检查。

如果Release版本中还有内存泄漏,那么 检查起来就麻烦很多了。

4 .总结:实际上Heap的内存泄漏问题是相当的好查的。

VC的提供的检查工具也不太少,但是如果是栈出了什么问题,恐怕就麻烦很多了。

栈出问题,一般不会产生内存泄漏,但是你的代码的逻辑上很有可能会有影响。

这个是最最痛苦的事情。

编程,就是小心,小心再小心而已。

你可能想看:
« 上一篇
下一篇 »

相关推荐

php实时推送,php实地培训

2026年10月05日

53阅读

php乱码出现问号的原因,php乱码出现问号的原因有哪些

2026年10月05日

44阅读

php一句话木马,一句话木马ctf

2026年10月05日

48阅读

php获取数组长度,php中如何获取数组的长度

2026年10月05日

50阅读

php面试题库及答案,php程序员面试真题库

2026年10月05日

47阅读

phpcontent-type修改,php源码二次修改需要多少钱

2026年10月05日

42阅读