刚接触.net开发时,还真不适应。曾经在开发PhP应用时,很多事情都要亲历亲为。就像一个侠客一样,你要会很多个体技能,这样才能披荆斩棘。但.net不同,你要当的是个机械师,学会各种工具,开着坦克向前进,管他深沟还是丛林,你都不需要去关心。开始的时候总是想试图把坦克搞清楚,在把自己变成坦克。后来才发现这个与解决问题背道而驰,于是悬崖勒马。学会发挥坦克的威力,而不是去制造坦克。
其中一个重甲坦克就是VSTS, 大家都见识过,功能俱全,和其他武器装备整合可算是天衣无缝。对于开发者来说,最重要的莫过于Debug功能了,真可谓应你之所需,有你只未见。但有些环境下,重甲武器就会变得束手束脚。因为真实的客户上线环境,一般都是派不上大用场。这时我们就需要轻型装甲步兵车-Windbg作为前哨,刺探军情,
言归正传,Windbg到底是什么呢?全名Debugging Tools for Windows,名字很平淡,但功能很牛X。相信第一次看到Windbg相关文档,一定是目瞪口呆,惊叹不已,然后是望而却步。但不是有句话说“千里之堤溃与蚁下”,我们只要找到一些容易下手的点,然后由点及线,由线及面,由面成体,那就没有肯不下得骨头。这技能可谓是程序员行走江湖必备,要时时刻刻修炼。又扯远了,我们在回来看看Windbg到底能调试什么。(以下摘自msdn)
Applications, services, drivers, and the Windows kernel.
Native 32-bit x86, native Intel Itanium, and native x64 platforms.
Microsoft Windows NT 4.0, Windows 2000, Windows XP, Microsoft Windows Server 2003, Windows Vista and Windows Server 2008.
User-mode programs and kernel-mode programs.
Live targets and dump files.
Local and remote targets.
是不是很强大,我们先找软的捏。作为开发者,我们开发的大部分都是应用程序。找对我们最有用,最熟悉的下手(这话有点歧义。。。)— Applications。下面来点干的。开发者的最爱 - Sample。
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Threading;
5
6 namespace Test
7 {
8 class Program
9 {
10 static int count = 1000;
11
12 static void Main(string[] args)
13 {
14 try
15 {
16 while (true)
17 {
18 Thread appleThread = new Thread(Drawing);
19 appleThread.Start("apple");
20
21 Drawing("tomato");
22 }
23 }
24 catch (Exception e)
25 {
26 Console.WriteLine(e.Message);
27 }
28 }
29
30 static void Drawing(object thing)
31 {
32 for (int i = 1; i < count; i++)
33 {
34 Console.WriteLine(thing);
35 }
36 }
37 }
38 }
编译成功并双击test.exe运行(我们把它当做客户上线运行的程序)。这时Apple和tomato交替的打印在屏幕上。客户说系统出现了问题,但是我们通过log和逻辑上得检查,都没有发现线索。这时我们就需要调试获取信息,客户的机器不是开发环境,一定是没有VS的,你总不能让客户装一个吧(VS可是很贵的)。此时windbg登场亮相。运行windbg,选择file->attach to a process...,这时弹出一个进程列表对话框,选择你要调试的进程(Test.exe)。
这时候你会发现程序停止了打印,这说明我们已经成功的attach到这个程序上。下面我们来介绍一些常用的命令。
在命令框里输入 “g” ,这时程序又进入了运行状态(类似我们在VS里使用 f10跳过当前断点)。那我们怎么再次断开呢,使用Ctril + break快捷键就可以搞定了。(或者Debug->break)
.hh 帮助文档
.cls 清除屏幕内容
!help 查看 mscorwks下的命令
!dumpheap 查看堆栈内所有的本应用程序对象
~*e !clrstack 查看所有线程的callstack
~*e !pe 查看所有线程的exception
!do 2f78d93c 查看2f78d93c上的对象
!threads 查看当前所有的线程状况
我们通过这些命令可以获取,进程信息,callstack信息,以及exception的信息。这些东西对我们分析问题,找到线索有很大的帮助。将在以后的文章中结合 out of memory 和 high cpu 的实例做具体的分析。
当我们无法再现场解决的问题,我们需要更多的人还有精力来做分析。但是我们总不能把客户的机器抱回家吧。所以windbg有一个很好的功能。就是把当前应用程序的内存空间和运行状态保存到文件。我们只需输入以下命令 “.dump /ma D:/test.dump”, 一个dump文件就创建好了,我们可以随时的进行分析。