Windows Phone App的dump文件实例分析-Stack Overflow
前言
这篇文章我们一起来分析一个从Windows Phone Dev Center上下载下来的dump file。首先按照我上一篇的步骤设置好我们的Windbg,并按住Ctrl +D打开dumpfile。可以看到下面的界面:
分析一个dump file可以分解为4个步骤,第一步是信息收集,第二步是定位异常上下文,第三步分析和推理出现问题的原因,第四步分析和定位我们的源代码并进行修复和验证。
信息收集
我们可以使用一些命令浏览一下这个dump file对应的系统版本和一些模块的信息辅助我们后面的分析。
1. version命令,查看系统版本号
2. lm命令,显示当前加载的模块。
可以使用lmv命令查看所有模块的详细信息,如果想看某一模块的详细信息,需要使用参数m,比如查看System_Data_Linq_ni.dll的详细信息,”lmv mSystem_Data_Linq_ni”

定位异常上下文
当异常发生的时候,寄存器的上下文会被异常分发器保存在栈上。我们可以通过一些方法找到并恢复发生异常时候的上下文,从上下文中找到我们需要的信息,这里使用”!analyze -v”命令。
1. 首先确认发生异常的线程。有时候发生异常的线程不止一个,我们在使用 “!analyze –v”之前需要确认发生异常的线程。使用”~* kvb”命令来查看所有线程的调用堆栈。”~*“ 命令是枚举所有的线程,”kvb“命令是列出线程的调用堆栈。
可以发现所有的线程都是等待状态,只有线程0不是,从线程0的callstack可以看出来线程0就是我们要找的发生异常的那个线程,。
2. 切换到发生异常的线程,”~0 s”
3. 使用“!analyze –v”,这个扩展命令来帮助我们找到发生异常时候的上下文,并显示当时的调用堆栈,有些情况下给出的调用堆栈并不是发生异常的第一现场,遇到这种情况我们需要进一步分析。

分析和推测
在上面的显示中,我们发现一个很有意思的托管调用堆栈,里面反复出现了”System.Diagnostics.StackTrace..ctor()+0x12”。看起来StackTrack这个类型的对象在构造的时候调用了自己的成员函数GetStackFramesInternal,而这个函数又去构造了新的StackTrack的对象,如此反复以至于发生了循环调用而导致栈被耗尽,这里并没有给出与我们的代码相关的调用,看起来很像一个.net framework的bug。那么为什么会发生这样的调用呢?让我们继续进行分析,看看是哪里引发了这个调用。
为了找到更多的线索,我们可以进一步查看发生异常的线程栈里都保留了什么,我们可以通过”!teb”命令来查看当前线程的属性,并找到栈的基址和大小,有了栈的基址和大小,我们就可以查看里面的内容了。
1. 查看当前线程的属性,”!teb”命令
2. ”dps + 地址范围”命令可以让我们查看栈里面保留的信息。
跳过这些无效的内容,我们继续往后查看。
红线的模块和函数正是我们App中的代码,我们可以做一个大胆的推理在这里。我们的函数DecrementPendingAndFinishIfNecessary调用了Logger.Info函数,这个函数使用了系统的StackTrace.CaptureStackTrace来获取当前的调用堆栈。那么为什么这个函数StackTrace.CaptureStackTrace又会去构造它自己的对象呢?让我们打开我们程序的源代码进一步分析。
分析和定位我们的源代码
打开我们的代码并找到Logger.Info的实现,红色的代码正是验证了我们上面的推理。在一些极端的形况下,StackTrace会创建失败并扔出异常,这个异常恰好被后面的catch块捕获再次调用了Logger的函数,而这个函数会再次创建StackTrace类型的对象,继续触发异常导致了反复的调用。
private static void WriteLine(Level level, string message)
{
try
{
if (0 == message.Length)
{
return;
}
StackTrace st = new StackTrace(); // 1. 这里exception
string name = st.GetFrame(2).GetMethod().Name;
string prefix = string.Format("[{0}]@{1}", level, name);
message = prefix + "-" + message;
}
catch (Exception e)
{
Logger.Fatal("Faild in WriteLog,message:" + e.Message); // 2. 然后执行这里
}
} public static void Fatal(string message)
{
WriteLine(Level.Fatal, message); //3. 这里继续执行1, 1 继续exception
}
知道了原因,我们就可以修改代码来修复了,最简单的方法就是先去掉catch里面的调用。
后续问题
那么为什么系统的StackTrack的GetStackFramesInternal会失败呢?感兴趣的同学可以尝试反编译命令来查看里面的细节。
分享代码,改变世界!
Windows Phone App的dump文件实例分析-Stack Overflow的更多相关文章
- Windows Phone App的dump文件实例分析- System.ExecutionEngineException
前言 在开始这篇文章之前我们先来讲讲如何从高度优化的Release版的Dump中找到正确的异常上下文地址,并手动恢复异常发生的第一现场. 1. 什么是异常上下文 简单来说,在windows体系的操作系 ...
- Windows Phone App的dump 文件分析
前言 我们在发布了自己的App以后,Windows Phone的Error Report机制会帮助我们收集程序的崩溃信息并发送到微软的服务器上,这可以辅助开发者提高App的稳定性. 那么如何利用这些d ...
- HTTP的上传文件实例分析
这个是http文件传输的一种格式,当时不知道这种格式,废弃. HTTP的上传文件实例分析 由于论坛不支持Word写文章发帖. 首先就是附件发送怎么搞,这个必须解决.论坛是php的.我用Chrome类浏 ...
- 干货分享丨jvm系列:dump文件深度分析
摘要:java内存dump是jvm运行时内存的一份快照,利用它可以分析是否存在内存浪费,可以检查内存管理是否合理,当发生OOM的时候,可以找出问题的原因.那么dump文件的内容是什么样的呢? JVM ...
- linux core dump 文件 gdb分析
core dump又叫核心转储, 当程序运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在一个core文件中, 叫core dump. (linux中如果内存越界会收到SIG ...
- windows程序崩溃生成dump文件
第一种: 通过任务管理器:这种适用在程序挂了(crash)的时候进程还未退出,比如我运行程序,出现了下面的错: 此时打开任务管理器,右击相应进程,点击"Create Dump File“: ...
- Windows Store App 用户库文件分组
在Windows应用商店应用程序中浏览用户库中的文件时,可以将文件或者文件夹分组显示,以便于进行分类浏览,这类似于音乐库中的文件可以按照艺术家名称.创建日期或者评级等多种方式进行分类.本节内容将会介绍 ...
- Windows Store App 用户库文件操作
(1)获取用户库位置 如果想要通过应用程序在用户库中创建文件,首先需要获得用户库中指定的位置,例如图片库.文档库等.这里值得注意的是,在获取用户库的位置之前,必须在Windows应用商店项目的清单文件 ...
- Windows Store App 用户库文件夹操作
上面介绍了与用户库文件有关的操作,包括创建.读写等,下面将介绍与用户库文件夹相关的操作. 与文件操作一样,想要对用户库文件夹进行操作,需要首先获取用户库的相应位置,获取的方法上面已经介绍过了,这里不再 ...
随机推荐
- Linux网络栈下两层实现
http://www.cnblogs.com/zmkeil/archive/2013/04/18/3029339.html 1.1简介 VLAN是网络栈的一个附加功能,且位于下两层.首先来学习Linu ...
- JSP日期时间转C#
DateTime.ParseExact("Wed Aug 03 16:46:24 CST 2016", "ddd MMM dd HH:mm:ss CST yyyy&quo ...
- 下拉框数据的动态选择,类似级联ajax刷新数据
简单的两个下拉列表,第二个中的数据与第一个下拉框相关: --------------------var selected = $(this).children('option:selected').v ...
- SEO是企业发展的永恒主题
最近接触很多客户问同一个问题,明明自己的网站花的时间很多,界面设计的很美,该考虑到的优化都考虑了,反而我那么优秀的网站却不如一个自己行业里的一个垃圾网站排名高,我没排名而对方的排名却很高?我每天坚持更 ...
- JS-Number
Number 是对原始数据的封装 语法: var myNum=new Number(value);//返回一个新创建的 Number 对象 var myNum=Number(value);//把自己的 ...
- ifmodule
<IfModule> 指令 说明 封装指令并根据指定的模块是否启用为条件而决定是否进行处理 语法 <IfModule [!]module-file|module-id ...
- 健忘vs总结
上周入职新公司,报道之前自己也曾想过要从头开始,用一个新的精神面貌来迎接新的起点,培养一些新的习惯. 周四是15日,新公司的发薪日(当然还没有我的份~),小组群内一个刚毕业的新人兴冲冲的说终于领到第一 ...
- ubuntu 下安装boost库
ubuntu下安装boost库,,在网上试了一些其他人推荐的libboost-dev 但是会缺少,编译程序会报错: /usr/bin/ld: cannot find -lboost_serializa ...
- webpack配置
1.初始化webpack npm install webpack -g (全局安装) npm init (初始化packge.json) npm install webpack --save- ...
- 使用doxygen制作C代码文档
使用doxygen制作C代码文档 C 代码注释风格约定 行间注释 /*! * * 这里是注释 * */ 行内注释 <code here> /*! 这里是注释 */ doxygen 风格的宏 ...