人生是一场不能存盘的RPG,我只能尽量多搞几个Screenshot

May 28, 2006

WinDbg+SOS实例

Filed under: WinDbg&SOS

出自
 SOS: It’s Not Just an ABBA Song Anymore(John Robbins)
 http://msdn.microsoft.com/msdnmag/issues/03/06/Bugslayer/
 
源码:
//——————————————————–
using System ;
using System.Diagnostics ;

namespace ExceptApp
{
    enum Days { Sat = 1 , Sun , Mon , Tue , Wed , Thu , Fri } ;
   
    class DoSomething
    {
        public void Doh ( String StrParam , Days ValueParam )
        {
            Console.WriteLine ( StrParam ) ;
            Console.WriteLine ( ValueParam.ToString ( ) ) ;
            throw new ArgumentException ( "Throwing an exception" , "x" ) ;
        }
       
        public void Reh ( int i , String StrParam )
        {
            Console.WriteLine ( "Reh = " + i ) ;
            String s = "Tommy can you see me? " + StrParam ;
            Days e = Days.Fri ;
            Doh ( s , e ) ;
        }
       
        public void Mi ( Object o )
        {
            Console.WriteLine ( "Mi = " + o.ToString ( ) ) ;
            String LocalStr = "Can you see me?" ;
            Reh ( 0x42 , LocalStr ) ;
        }
       
        public void Fa ( )
        {
            Mi ( this ) ;
        }
    }
 class Class1
 {
  static void Main(string[] args)
  {
      try
      {
          DoSomething x = new DoSomething ( ) ;
          x.Fa ( ) ;
      }
      catch
      {
      }
  }
 }
}
 
1. 何让WinDbg 拦截CLR Exception
使用菜单Debug->Event Filter打开Dialog
Click "Add"
enter "0xE0434F4D"
Select "Enabled" in the Execution group box
select "Not Handled" in the Continue group box

2. 使用 !thread 显示进程或一个dump文件中所有的managed线程

ThreadCount: 2
UnstartedThread: 0
BackgroundThread: 1
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
                                      PreEmptive   GC Alloc           Lock
       ID OSID ThreadOBJ    State     GC       Context       Domain   Count APT Exception
   0    1  188 00181148      a020 Enabled  013c4b6c:013c5fe8 0014f238     0 MTA System.ArgumentException (013c4ad0)
   2    2  94c 0018ae58      b220 Enabled  00000000:00000000 0014f238     0 MTA (Finalizer)

OSID为 win32 thread id
Domain 线程所在的app domain
Exception 可能包含多种含义, 以上的信息表明1号线程引发了ArgumentException, 2号线程是Finalizer
          这个字段的值还可能是 (Threadpool Worker), (Threadpool Completion Port), or (GC),这些
          都是.net的执行线程.

3. 使用Windbg的 ~ 系列命令
   ~     :  显示所有的线程
   ~*    :  显示所有的线程
   ~.    :    显示当前线程
   ~#    :  引发异常的线程
   ~2    :  2号线程

使用~会显示
.  0  Id: b64.188 Suspend: 1 Teb: 7ffde000 Unfrozen
   1  Id: b64.a14 Suspend: 1 Teb: 7ffdd000 Unfrozen
   2  Id: b64.94c Suspend: 1 Teb: 7ffdc000 Unfrozen
  
   可见, 进程中除了2个.net线程,还存在一个win32线程.
     
4. 使用 !clrstack (或!dumpstack)
   !clrstack -a       查看所有信息,包括参数和局部变量
   !clrstack -l       查看局部变量
   !clrstack -p       查看参数
  
   ~*e!clrstack       查看所有线程的调用栈.
  
使用 !clrstack -a 显示

OS Thread Id: 0x188 (0)
ESP       EIP    
0012f350 7c81eb33 [HelperMethodFrame: 0012f350]
0012f3f4 00df02e7 ExceptApp.DoSomething.Doh(System.String, ExceptApp.Days)
    PARAMETERS:
        this = 0x013c1c44
        StrParam = 0x013c3f18
        ValueParam = 0x00000007

0012f418 00df0237 ExceptApp.DoSomething.Reh(Int32, System.String)
    PARAMETERS:
        this = 0x013c1c44
        i = 0x00000042
        StrParam = 0x013c1c6c
    LOCALS:
        <CLR reg> = 0x013c3f18
        0x0012f41c = 0x00000007

0012f438 00df01a0 ExceptApp.DoSomething.Mi(System.Object)
    PARAMETERS:
        this = 0x013c1c44
        o = 0x013c1c44
    LOCALS:
        0x0012f438 = 0x013c1c6c

0012f450 00df0134 ExceptApp.DoSomething.Fa()
    PARAMETERS:
        this = 0x013c1c44

0012f458 00df00b8 ExceptApp.Class1.Main(System.String[])
    PARAMETERS:
        args = 0x013c1c34
    LOCALS:
        0x0012f458 = 0x013c1c44

0012f69c 79e88f63 [GCFrame: 0012f69c]

以上内容对应于.net2.0 和原文中有所不同.

5. 使用dd 0x**** 可以查看内存中的值

6. !DumpMT [-MD] <MethodTable address>
    显示位于某个地址的 method table的信息, 每个managed object都会有个method table
   
7. !DumpClass 显示class所有信息

8. !Dumpmodule

9. !Dumpobject
    对于一个static 变量,会显示domain 和 静态变量在domain中位置, 这些信息被>>和<<扩起.
   
    790fa3e0  4000099       10        System.String  0   shared   static Empty
    >> Domain:Value  0014f238:790d6584 <<

10.!DumpStackObjects 显示当前线程的堆栈上的所有对象.

设计模式纵横谈(15)Command 命令模式

Filed under: Design Pattern

隔离 行为请求者 和 行为实现者 之间的耦合.
将行为抽象成object.
行为的请求者传递一个对象,该对象表达了一个方法(行为)

//== Version 1.
class Application
{
    public void Show()
    {
        Document doc = new Document();
        doc.ShowText();
       
        Graphics graph = new Graphics();
        graph.ShowGraphics();
    }
       
}

class Document
{
    public void ShowText()
    {
        …
    }
}

class Graphics
{
    public ShowGraphics()
    {
        …
    }
}

此时,Application 直接依赖于 document 和 graphics的showXX()这样的
具体行为实现.
考虑如何实现undo,redo,需要添加大量的代码.

//== Version 2.
public interface Command
{
    public void Show();
    public void Undo();
    public void Redo();
}

//==这个设计违背了单一职责原理,
class Document : Command
{
    public virtual void Show()
    {
   
    }
}

class Graphics : Command
{
    public virtual void Show()
    {
   
    }
}

class Application
{
    Stack<Command> commands;
    Stack<Command> undoList;
   
    public void Show()
    {
        foreach(Command c in list)
        {
            c.Show();
        }
    }
   
    public void Undo()
    {
        if(canUndo)
        {
            Command command = commands.Pop();
            command.Undo();
            undoList.Push(command);
        }
    }
   
    public void Redo()
    {
        if(canUndo)
        {
            Command command = undoList.Pop();
            command.Redo();
        }
    }       
}

//== Version 3.  扩展已有的类
//已存在,实现细节
class Document : Command
{
    public virtual void Show()
    {
   
    }
}

class Graphics : Command
{
    public virtual void Show()
    {
   
    }
}

//==实现command 模式
public interface Command
{
    public void Show();
    public void Undo();
    public void Redo();
}

//==具体化的行为对象,
class DocumentCommand : Command
{
    Document doc;
   
    public DocumentCommand(Document doc)
    {
        this.doc = doc;
    }
   
    public void Show()
    {
        doc.ShowText()
    }
   
    public void Undo()
    {
        …
    }
   
    public void Redo()
    {
        …
    }
}

此时,Application不再依赖于document和graphics这样的细节, 而是依赖于Command这样的
抽象,体现了依赖导致原则.

Command和Delegate之间的选择:

Command更趋向于oo的特征,更符合抽象的原则. Delegate 更灵活






















Get free blog up and running in minutes with Blogsome
Theme designed by Hadley Wickham