最近项目突然收到了一个紧急的问题报告 - 用户在进行某些关键操作的时候整个软件突然就crash掉了。幸好产品继承了自动抓取dump的功能。。。

 
收到dump之后,通过windbg打开,查看相应的callstack。迅速定位到出错的线程。在调用MapViewOfFile()的时候没有map成功导致crash。
 
接下来,我们需要知道为什么为何map失败?通过GetLastErrorCode(),我们得知进程OutOfMemory导致map失败。MapViewOfFile()需要映射512KB(4Mb)连续内存,而通过!address -summary命令,我们发现系统里最大的连续内存块为1.5Mb。Crash因此发生了。
 
 
至此,我们可以肯定,该crash是由于memory leak造成MapViewOfFile()失败。那么,是什么leak了?重新看上面的输出信息,我们可以看到,MEM_MAPPED使用的内存高达934Mb,MEM_PRIVATE使用的内存为805Mb。据此,我们怀疑,产品里所使用的memory mapped file可能会存在大量的leak。
 
运行命令!address -f:MEM_MAPPED,会得到类似的输出:
 
第三列,也就是RgnSize,为当前MMF的映射窗口大小。查看了该输出,我们发现,窗口大小为512kB的文件在500个左右,而大小为256KB的文件多大1800个。据此,我们可以锁定这些256KB的MMF文件。
 
下面的问题,就是,谁映射了这么多的MMF文件?在此不同的项目可以有不同的方法。如果你很熟悉项目数据的话,你可以先通过dd查看一下该256KB的内容都是啥?有没有你所熟悉的内容?如果是字符串的话那就更容易定位问题的所在地方了。
 
这里,我们假设我们不熟悉文件的内容,从而无法猜测这些数据是谁产生的。我们只能采取其他办法。
 
上面输出的第一列,也就是BaseAddr,为该map view的地址。如果我们要使用该map view的话,我们必须要有对应的指针指向该view。因此,我们随机选了一个256KB的view的baseaddress,然后通过下面的命令查找谁还指向了这块内存。
 
 
从该输出我们能够看到,大概有10多个地方保存有该指针地址。接下来,我们就需要查看谁,也就是那些类的instance还保存这些地址。此处没有其他好的办法,只能在这些地址四处通过dds命令来查看是否有对象的symbol。
 
在查看了多个地址之后,我们发现,有一个vftable为CMMFSerializer的对象。这给了我们极大的肯定:该类名里有MMF!十有八九是该类的leak!
 
接下来,我们的目标为谁创建了CMMFSerializer对象而没有销毁?首先,我们通过x命令来获得CMMFSerializer的虚表地址,这样我们就能够在heap里搜索这些对象都存在哪里。
 
然后,运行!heap命令,就能够查看到拥有这些对象的地址了。
从我们的输出能够看到,大量的CommunicatorObj对象存在heap里。这就说明了CommunicatorObj这些对象没有被删除掉。从而,我们可以做这样的结论:CommunicatorObj的泄漏导致了如此之多的MMF的泄漏,以及很高的MMF_PRIVATE使用率如此之高。剩下来的工作就很简单了,看看代码,分析分析哪些地方使用了CommunicatorObj。
 
 

MemoryMappingFile泄漏分析过程的更多相关文章

  1. 一个驱动导致的内存泄漏问题的分析过程(meminfo->pmap->slabtop->alloc_calls)

    关键词:sqllite.meminfo.slabinfo.alloc_calls.nand.SUnreclaim等等. 下面记录一个由于驱动导致的内存泄漏问题分析过程. 首先介绍问题背景,在一款嵌入式 ...

  2. Erlang 内存泄漏分析

    随着项目越来越依赖Erlang,碰到的问题也随之增加.前段时间线上系统碰到内存高消耗问题,记录一下troubleshooting的分析过程.线上系统用的是Erlang R16B02版本. 问题描述 有 ...

  3. Java内存泄漏分析与解决方案

    Java内存泄漏是每个Java程序员都会遇到的问题,程序在本地运行一切正常,可是布署到远端就会出现内存无限制的增长,最后系统瘫痪,那么如何最快最好的检测程序的稳定性,防止系统崩盘,作者用自已的亲身经历 ...

  4. Android内存泄漏分析及调试

    尊重原创作者,转载请注明出处: http://blog.csdn.net/gemmem/article/details/13017999 此文承接我的另一篇文章:Android进程的内存管理分析 首先 ...

  5. Android 内存泄漏分析与解决方法

    在分析Android内存泄漏之前,先了解一下JAVA的一些知识 1. JAVA中的对象的创建 使用new指令生成对象时,堆内存将会为此开辟一份空间存放该对象 垃圾回收器回收非存活的对象,并释放对应的内 ...

  6. Java内存泄漏分析系列之六:JVM Heap Dump(堆转储文件)的生成和MAT的使用

    原文地址:http://www.javatang.com JVM Heap Dump(堆转储文件)的生成 正如Thread Dump文件记录了当时JVM中线程运行的情况一样,Heap Dump记录了J ...

  7. Java内存泄漏分析系列之五:常见的Thread Dump日志案例分析

    原文地址:http://www.javatang.com 症状及解决方案 下面列出几种常见的症状即对应的解决方案: CPU占用率很高,响应很慢 按照<Java内存泄漏分析系列之一:使用jstac ...

  8. Java内存泄漏分析系列之二:jstack生成的Thread Dump日志结构解析

    原文地址:http://www.javatang.com 一个典型的thread dump文件主要由一下几个部分组成: 上图将JVM上的线程堆栈信息和线程信息做了详细的拆解. 第一部分:Full th ...

  9. Java内存泄漏分析系列之一:使用jstack定位线程堆栈信息

    原文地址:http://www.javatang.com 前一段时间上线的系统升级之后,出现了严重的高CPU的问题,于是开始了一系列的优化处理之中,现在将这个过程做成一个系列的文章. 基本概念 在对J ...

随机推荐

  1. ExtJS4之Ext.MessageBox的各种用法

    1. Ext.Msg.alert(String title,String msg)[Ext.MsssageBox.alert(Sting title,Sting msg,fn)]与javascript ...

  2. 谈谈防止Ajax重复点击提交

    首先说说防止重复点击提交是什么意思. 我们在访问有的网站,输入表单完成以后,单击提交按钮进行提交以后,提交按钮就会变为灰色,用户不能再单击第二次,直到重新加载页面或者跳转.这样,可以一定程度上防止用户 ...

  3. [分享] VIM 常用命令及游戏练级

    分享一个不错的文章,讲解了 VIM 的常用命令. http://coolshell.cn/articles/5426.html 另,介绍一个可以帮助熟悉VIM命令的练级游戏. 游戏地址:http:// ...

  4. 习惯&感恩

    A不喜欢吃鸡蛋,都给了B吃,刚开始B很感谢,久而久之便习惯了.习惯了,便理所当然了. 后来有一天,A将鸡蛋给了C,B就不爽了.她忘记了这个鸡蛋本来就是A的,A想给谁都可以. 为此,她们大吵一架,从此绝 ...

  5. VennDiagram 画文氏图/维恩图/Venn

    install.packages("VennDiagram")library(VennDiagram) A = 1:150B = c(121:170,300:320)C = c(2 ...

  6. [CF580B]Kefa and Company(滑动窗口)

    题目链接:http://codeforces.com/problemset/problem/580/B 某人有n个朋友,这n个朋友有钱数m和关系s两个属性.问如何选择朋友,使得这些朋友之间s最大差距小 ...

  7. 《OD学hadoop》第一周0626 作业二:Linux基础

    一.打包压缩 知识点: tar -zxvf -C PATH tar -jxvf tar -zcvf tar -jcvf tar:打包命令 -z 打包同时gzip压缩 -j 打包同时bzip2 -c 打 ...

  8. HeadFirst jsp 02 (体系结构)

    当请求到来时, 必须有人实例化 servlet, 或者至少建立一个新的线程来处理这个请求. 必须有人调用 servlet 的 doPost()或 doGet()方法. 另外还的有人管理 servlet ...

  9. 网络攻击之二:XSS(之一是SQL注入,前面有文章)

    学习了 http://www.oschina.net/question/565065_57506 (这里做了转载 http://blog.csdn.net/stilling2006/article/d ...

  10. [Android] Android开发优化之——使用软引用和弱引用

      Java从JDK1.2版本开始,就把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期.这四种级别由高到低依次为:强引用.软引用.弱引用和虚引用. 这里重点介绍一下软引用和弱引用. ...