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 用户库文件夹操作
上面介绍了与用户库文件有关的操作,包括创建.读写等,下面将介绍与用户库文件夹相关的操作. 与文件操作一样,想要对用户库文件夹进行操作,需要首先获取用户库的相应位置,获取的方法上面已经介绍过了,这里不再 ...
随机推荐
- [Arduino] Arduino猪头笔记
1. 步进电机驱动 今天才发现....原来在不同的步进电机驱动模块里面,循环时钟是不一样的.... 步进电机驱动模块以及电路配置: 驱动代码的主要部分: int sp_param = 16383; d ...
- 关于启动 SecureCRT 遇到一个致命的错误且必须关闭
--------------------------SecureCRT---------------------------SecureCRT 遇到一个致命的错误且必须关闭. 一个崩溃转储文件已创建于 ...
- IOS 支付、性能调试、IPv6兼容支持等
微信支付 支付宝支付 性能调试 IPv6兼容支持 APP引导页框架
- Windows Desktop 调用 WinRT api
<Reference Include="Windows"> <HintPath>..\..\..\..\..\..\Program Files (x86)\ ...
- Codeigniter 在Active Record中限制批量更新数目
今天手头电商项目有个需求是:将订单中的优惠券自动发放给买家,所以要只更新优惠券表中的某几行数据,查了手册和网络都没有解决办法. 一开始用循环和遍历来做都是错的,因为update语句一下就更新掉所有符合 ...
- sqlserver中的表值函数和标量值函数
顾名思义:表值函数返回的是表,而标量值函数可以返回基类型 一.表值函数 用户定义表值函数返回 table 数据类型.对于内联表值函数,没有函数主体:表是单个 SELECT 语句的结果集. 以下示例创建 ...
- MVC模式下向qq邮箱发送邮件
将已经保存在数据库中的密码通过邮件发送到qq邮箱中.用的ssm框架,其中的config文件要先配置好. 用到的jar包有gson-2.2.1.jar,gson.jar,mail.jar,activat ...
- java四种内部类
内部类有成员内部类,局部内部类,匿名内部类,静态内部类. 1,成员内部类package innerClass; public class InnerClassTest { String s1=&quo ...
- js读写Cookie问题(Cookie存储时长、Cookie存储域)汇总
在采集网站用户行为数据/使用js对用户行为做交互时,经常会使用到Cookie,了解Js Cookie的读写,以及一些细节,非常重要. 什么是Cookie 所谓Cookie,只是一条极为短小的信息, ...
- C++中有符号/无符号数比较
原创文章,欢迎阅读,禁止转载. 在我的程序中有如下代码编译被警告了 if(list.size()>msize){...} warning C4018: '<' : signed/unsig ...