dotnet core@IT·互联网程序员

我是这么学习 WinDBG 的

2017-05-21  本文已影响287人  远程板砖

WinDBG 的命令简(难)洁(懂),多(难)样(记),功(反)能(人)强(类)。许多同学都感觉它功能强大但是不容易上手。今天我介绍另一种方式希望对大家有所帮助。

WinDBG 是一个调试器,那么什么是调试呢?我的理解,调试可以认为是确认应用程序在此刻的状态正确与否。如果状态正确,那么一切正常,如果状态错误,那么说明应用程序的执行出现了问题。而应用程序的状态是什么呢?其实就是应用程序在内存中的表示。那么,如果我们能够理解应用程序在内存中的构成,那么我们就可以找到各种各样的状态,从而判断程序运行的正确性了。

因此,WinDBG 的命令是什么并不重要,重要的是你知道如何用这些命令探索应用程序各种状态之间的联系。下面我们就先简要的看一看应用程序的状态是什么样子的(我以 CLR 的应用程序为例)。

应用程序在内存中是这样的

这篇文章的关键在于思路而非包罗万象的介绍应用程序在内存中的表示。如果要深入探索,还需要多下下功夫。

应用程序的最上层结构是进程,进程中包含了正在执行的若干线程。

如果我们画一张图,那么这张图就类似这样:

随便一整的应用程序的运行时结构

调试就是一次旅游

那么调试就是从这张图的任意一个点进入,并且通过应用程序运行时状态的各个部分的关系,通过图中的线进行任意的游走,确定每一个部分是否正确的过程。

通过上述分析,那么我们只要解决两个事情就可以了:

  1. 找一个入口点
  2. 在状态的各个部分之间游走

我们不妨来尝试一下。

找到一个入口点

现在请查一下 winDBG 的命令手册,你可以从网上搜到各种各样的资料。例如如下几个:

在状态的各个部分之间游走

现在我们有一个切入点了,那么我们就可以通过各个部分之间的关系将应用程序执行涉及到的信息一个不剩的找出来。例如:

旅游总结

综合前两个小标题的内容我们可以制定如下的旅游攻略:

使用 winDBG 命令在应用程序各部分间游走

此图不全,仅仅是为了抛砖,希望各位能够自己总结,形成自己的知识体系。

旅游也有套路

应用程序的内部结构还是有些复杂的。为了节省时间,大家都会总结各种套路。这就需要大家整理思路了。

例如,对于某次高的 CPU 占用。我选择先从线程入手。首先使用 !runaway 命令查看线程的 CPU 时间。发现 20 多个线程没完没了的执行了若干小时。而后通过 !clrstack 查看线程的调用栈发现这些线程的调用栈都在调用一个叫做 RenameXxx 的函数。

其实应用程序很少会出现巧合,因此怀疑这个函数有问题。使用 !clrstack -p 查看了一下函数的参数和局部变量,发现一个参数含有一个字符串变量,其长度已达 1MB。使用 !dumpobj 发现其内容为:fileName (1) (1) (1) (1) ... 至此基本断定这个函数里有死循环的逻辑了。

网上还有很多既有的套路。例如 Tess 的博客。强烈建议各位读者也用自己的博客、小本子、Evernote、OneNote 等各种媒介记录自己的旅游套路。不知不觉你就会成为 winDBG 调试的老司机。

其实,这篇博客不光是为 winDBG 写的。

上一篇下一篇

猜你喜欢

热点阅读