WinDBG调试dNet程序总结

来源:互联网 发布:一个人能备案几个域名 编辑:程序博客网 时间:2024/06/05 23:53

WinDBG工具简介

http://www.cnblogs.com/mashuping/archive/2009/03/28/1424168.html

对于一般的程序不需要使用WinDBG工具去调试,使用MDBG就OK
使用WinDBG + SOS调试.Net程序的一般步骤

1. 加载进程和SOS扩展

       a. F6或者使用菜单Files –> Attach to a process…来Attach一个托管进程
       b.使用命令.loadby sos mscorwks来加载SOS扩展(注意:.Net1.1时代的SOS扩展已经自带于下载安装的WinDBG中,从.Net2.0以后,SOS扩展已经自带到.Net框架中:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\SOS.dll,为了不至于引起混淆,最好的方法
就是使用前面的loadby调试器元命令来让WinDBG自己决定加载什么版本的SOS。 mscorwks表示.Net框架的工作站版本,现在我们安装的.Net Framework都是该版本)
       c.加载SOS后,使用命令.chain来查看调试链中是否已经成功包含SOS扩展,如下图的WinDBG输出就表示已经成功的加载了SOS:
      

2. 查看进程加载的模块并加载调试符号


       Attach到进程并顺利加载SOS扩展后,我们可以使用lm命令来查看当前进程已经加载的模块,WinDBG会列出一个模块加载列表,这个列表非常有用,我们后面设置断点,查看方法表和IL以及汇编代码都需要使用到相应的Module Name。另外对于我们常用的情况:调
试IISHost的进程,由于进程的名字都是w3wp,我们需要区分出哪个进程才是我们想要调试的Application,这个时候我们就可以通过lm命令列出的加载模块列表来判断:
 
       接下来我们就可以根据Module Name来给对应的Module加载调试符号库,由于在使用WinDBG进行调试的时候大多数时候我们都会查看汇编代码,所以加载调试符号对于辅助我们更好的看懂汇编代码和相关的变量命名是必须的,WinDBG默认会帮我们加载相关Module
的调试符号,我们也可以使用ld [ModuleName]来显示的加载某一个Module的调试符号,例如ld BasicDebugDemo指定加载BasicDebugDemo这个Module的调试符号。
 

3. 准备就绪,开始调试

       经过1,2两个步骤的准备,我们的调试环境已经准备好了,接下来就可以开始调试了,下面介绍一些重要的和常用的调试命令:
       1) 根据调试符号库的信息查看类或者方法在.Net执行引擎中的具体元信息,包括类的方法表地址,类在运行时的元信息(父类元信息地址,虚方法表地址等很多有用信息),这些信息是我们接下来调试的基础!使用命令!name2ee [ModuleName] [ClassName or 
MehodName]来进行查看,例如:!name2ee BasicDebugDemo BasicDebugDemo.Program:
        我们也可以使用!name2ee命令直接查看某个类方法的元信息: 
 
2) 有了上面得到的一个类的方法表的入口地址后,我们就可以使用!dumpmt [-md] [MethodTabel Address]来查看这个类中每一个方法的具体运行时信息(加带md选项表示我们要查询每一个方法声明的入口地址),例如我们利用上面得到的00993030这个地址,!dumpmt –

md 00993030:
 
3) 另外我们通过上面的!name2ee命令除了拿到MehodTable的地址外,还拿到了Program这个Class的运行时元信息地址EEClass Address,所以我们可以通过!dumpclass [Class Address]来查看这个类中的具体内容(比如其中的静态变量的地址等):
4) 上面提到了一个很重要的信息MehodDesc,得到这个MethodDesc有什么用呢?首先我们可以使用!dumpil [MethodDesc]来查看其编译后的IL代码:
5) 另外如果这个方法已经被JIT了,那么我们调用!dumpmd [MethodDesc]会得到下面的信息:
       接下来我们就可以使用!u [LocalCodeAddr]来查看生成的本地汇编代码:
 
6) 上面能获取的元信息我们基本上都获取了,有了这些元信息(主要是代码地址信息)我们要下断点就很简单了,我们有很多种方式来给我们的代码的指定位置加上断点P
    a.首先如果调试符号加载成功的话,我们可以直接使用很直观的原始方法命名来给指定的方法入口处加上断点:!bpmd [ModuleName] [MethodName],例如!bpmd BasicDebugDemo BasicDebugDemo.Program.CreateFooObject
    b.如果我们有MethodDesc,也可以直接使用!bpmd -md [MethodDesc]来给方法入口处加上断点,例如!bpmd -md 0099301c
   c.我们上面看到了本地汇编代码,所以我们也可以使用bp [CodeAddr]来给某个方法内部的某行代码加上断点。
   d.我们可以使用bl命令来列出所有已加载的断点,也可以使用bc [BreakPoint ID]命令来删除指定ID的断点(用bl命令列出的断点列表种有各个断点的ID),或者使用bc *来删除所有的断点。
    e.断点加载成功后,WinDBG会给出类似下面这样的提示:
         Found 1 methods...
MethodDesc = 00993028
Adding pending breakpoints...
    f.当我们的断点命中后,我们仍然可以像普通调试一样来使用F10 Step Out单步执行,使用F11来Step Into单步执行。注意:这里的单步执行,都是指单步汇编代码,而不是我们所写的代码。
7) 在命中断点后我们就可以通过查看类命令来查看栈和堆中的变量的值以及当前的调用堆栈:
  a.使用!clrstack可以查看当前的条用堆栈,使用!clrstack –l可以查看当前调用堆栈以及其上的局部变量和值,使用!clrstack –p可以查看当前调用堆栈上的参数变量以及值,使用!clrstack –a可以查看当前堆栈上所有局部变量和参数变量以及值(格式为

StackAddress =  StackValue)。!clrstack命令只会显示托管代码的调用堆栈,如果想查看完整的调用堆栈可以使用!dumpstack命令:
b.使用!dso命令可以查看堆栈上的所有对象
  c.使用!do [ObjectAddress]查看指定对象的具体内容:
 
8) 除了通过堆栈查看栈上的变量外,我们还可以直接通过!dumpheap来查看目前堆中的所有对象,但是由于一般情况下堆中存在的变量会非常的多(包含.Net框架里的很多预定义对象),所以直接使用!dumpheap得到的结果一般我们很难查看。大多数情况下,我们需要查

看的是堆中指定类型的对象,所以我们可以使用!dumpheap –type [ClassName]来查看指定类型的对象:
9)如何检查内存泄漏?WinDBG SOS中有一个很有用的命令!GCRoot [ObjectAddress]可以帮助我们查看指定对象的引用情况,这个信息可以很好的帮助我们分析那些本应该没有引用但却一直还存在有效引用的对象,由此发现我们代码中潜在的内存泄漏,同时我们也可以

观察到哪些对象是目前没有引用了,但是GC还没有回收的:
 

4. 总结


1) WinDBG不是专门用于调试.Net程序的工具,它更偏向于底层,可用于内核和驱动调试。进行普通的.Net程序调试还是使用微软专为.Net开发的调试工具MDBG更方便一些。但是WinDBG能看到更多的底层信息,对于某些特别疑难的问题调试有所帮助,例如内存泄漏等问题。
2) SOS扩展命令中最有用的命令是!help命令J,使用该命令可以列出所有可用的SOS扩展命令列表,使用!help [SOSCommandName]可以查看每一个具体扩展命名的详细使用说明,例如!help dumpheap就可以查看!dumpheap这个扩展命名的具体使用方法。多多利用!help命名可以很快上手SOS。
3) WinDBG本身的资料可以参考 张银奎 先生的《软件调试》一书,另外在互联网上也有非常多的WinDBG资料。
========

使用Windbg调试.Net应用程序

http://blog.csdn.net/kntao/article/details/7086616

1. 解决线上.NET应用程序的如下问题

崩溃
CPU高
程序异常
程序Hang死

2. 安装WinDbg

http://msdn.microsoft.com/en-us/windows/hardware/gg463009.aspx

3. 配置WinDbg

运行WinDbg->菜单->File->Symbol File Path->按照下面的方法设置_NT_SYMBOL_PATH变量:
在弹出的框中输入“C:\MyCodesSymbols; SRV*C:\MyLocalSymbols*http://msdl.microsoft.com/download/symbols”(按照这样设置,WinDbg将先从本地文件夹C:\MyCodesSymbols中查找Symbol,如果找不到,则自动从MS的Symbol Server上下载Symbols)。另一种做法是

从这个Symbol下载地址中http://www.microsoft.com/whdc/devtools/debugging/symbolpkg.mspx,下载相应操作系统所需要的完整的Symbol安装包,并进行安装,

4. 利用WinDbg里的adplus来获取dump文件

 Dump文件是进程的内存镜像。可以把程序的执行状态通过调试器保存到dump文件中。
在WinDbg安装目录里可以找到adplus.exe,把他拖入到命令行中,然后用命令
adplus.exe -hang -pn test.exe -o c:\dumps  // 抓取当前的dump文件
adplus.exe -crash -pn test.exe -o c:\dumps  // 监听应用程序,当crash时,获取dump文件
命令-pn :应用程序名,-p:应用程序pid,-odump文件输出路径

5. 利用WinDbg加载dump文件加载调试器

运行WinDbg->菜单->File->Open Cresh dump 打开dump文件,并加载.net调试器

.loadby sos mscorwks  .Net 3.5版本及以下
.loadby sos clr  .Net 4.0
如果服务器的.Net版本与本机不匹配需要服务器版本的mscordacwks.dll文件
并设置.sympath = mscordacwks_x86_x86_2.0.50727.3607.dl

6. WinDbg的基本命令

help  sos指令帮助
!threads  显示所有线程
!dumpheap  显示托管堆的信息
!clrstack  显示调用栈
!dumpobj  显示一个对象的内容
!dumparray  显示数组
!syncblk  显示同步块
!runaway  显示线程cpu时间
!gcroot  跟踪对象内存引用
!pe  打印异常

7. WinDbg的使用

当我在Form中执行这段代码:
[csharp] view plain copy print?
public Form1(){  
            InitializeComponent();  
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);  
        }  
    private void UnhandledExceptionProc(object obj){  
            try {  
                throw new Exception("1st chance");  
            } catch (Exception) {  
                MessageBox.Show("after 1st");  
            }  
            int d = 0;  
            int n = 1 / d;  
}  
并活动dump文件

用windbg打开dump文件后输入-pe:可以看到问题的所在。

异常如此重要,所以操作系统提供了对应的调试功能,可以使用调试器来检视异常。异常发生后,操作系统在调用用户态程序的异常处理函数前,会检查当前用户态程序是否有调试器加载。如果有,那么操作系统会首先把异常信息发送给调试器,让调试器有观察异常的

第一次机会,所以也叫做first chance exception,调试器处理完毕后,操作系统才让用户态程序来处理。
如果用户态程序处理了这个异常,就没调试器什么事了。否则,程序在unhandled exception崩溃前,操作系统会给调试器第二次观察异常的机会,所以也叫做second chance exception。
《Windows用户态程序高效排错》
分析以下代码:可以看出DummyObject 会占用很多内存,甚至导致内存溢出
[csharp]
private void MemeryLeakProc(object obj)  
    {  
        while (true) {  
            for (int i = 0; i < 100 * 1024; i++) {  
                DummyObject o = new DummyObject();  
                list.Add(o);  
            }  
            Thread.Sleep(1000);  
        }  
    }  
windbg命令:!dumpheap –stat 统计堆栈内存

线程Hang住的常见原因
-线程池或工作线程集中在某个耗时的工作当中,或者被其他线程锁住
核心问题,找到被hang住的线程
!threads
~*e!clrstack
!synblk
[csharp]
lock (syncRoot) {  
                int tp;  
                int io;  
                //ThreadPool.GetMaxThreads(out tp, out io);  
                for (int i = 0; i < 100; i++) {  
                    Thread hangThread = new Thread(HangProc);  
                    hangThread.Start();  
                }  
                MessageBox.Show("Press to release lock");  
            }  
[csharp]
  private void HangProc(object obj)  
  {  
   lock (syncRoot) {  
    n = 0;  
   }  
  }  

CPU高
-如果与业务量没有提升,有线程在长时间的处理
核心问题,找到占用CPU的线程
!runaway
~*e!clrstack
 
线程死锁出现的情况:
两个锁A,B,
一个线程已经拿到锁A,申请锁B,
另一个线程已经拿到锁B,申请锁A
核心问题:找到锁定的线程
!threads
!syncblk
~*e!clrstack
 
•两条指令可以解决大部分的问题
•!dumpheap –stat
•~*e!clrstack
 
========

WinDbg调试.NET程序入门

http://www.cnblogs.com/bluedoctor/p/4813125.html

自从来到新公司遇到性能问题后,需要想办法解决这个问题,但是一直没有合适的性能分析工具,然后找到StevenChennet 大神帮忙,他用WinDbg工具远程帮我分析了一个 dump文件,但是只看到键盘 “啪啪啪”,得到了结果,却不是很清楚WinDbg神奇具体如何使用的
。结果,第二天,性能问题又来了,总不能每次劳烦大神驾到,所以不得不自己开始学习WinDbg,这里记录一个入门过程。

1,首先,下载并安装WinDbg程序

从下面的地址打开:
https://msdn.microsoft.com/en-us/windows/hardware/hh852365
然后看到
Standalone Debugging Tools for Windows (WinDbg)
下载。
安装好后,在开始-》Windows Kits文件夹下有 WinDbg(x86),WinDbg(x64) 两个程序的快捷方式,如果你要调试
64位的程序,就用WinDbg(x64)。


2,创建内存转储文件

可以在任务管理器,进程-》创建转储文件 里面,得到当前进程的dump文件,我是用下面这个程序来生成转储文件的:
Procdump
下载地址:https://technet.microsoft.com/en-us/sysinternals/dd996900.aspx
有关 ProDump程序的使用,可以参考下面2个博客文章:
High CPU Dump收集工具 - ProcDump使用方法

介绍一个好用的抓取dump的工具-ProcDump

在命令行,运行这个程序:

procdump -ma mydotNetApp.exe d:\myapp.dmp
运行后,将得到一个myapp.dmp 文件,如果这个文件是在本机生成的,那么VS2013可以直接打开这个文件并可以分析托管内存,但是,往往内存转储文件是 在服务器生成的,而服务器又很可能跟开发环境不一样,所以才需要本文介绍的 WinDbg来调试。

3,配置调试环境


首先,打开我们刚才的转储文件,可以使用菜单命令打开:
File->Open Crash Dump...
打开后,会显示程序当时运行所在的环境,此时,会提示符号文件没有发现:

*** ERROR: Symbol file could not be found.  Defaulted to export symbols for ntdll.dll - 
如果不配置,使用命令的时候会提示错误,比如:

复制代码
0:000> .loadby sos clrjit
0:000> !tp
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for clr.dll - 


************* Symbol Loading Error Summary **************
Module name            Error
clr                    PDB not found : e:\appserver\symbols\dll\clr.pdb
复制代码
e:\appserver 是我的dmp文件所在的目录,它默认是到symbols 子目录去找符号文件去了。

然后,配置下使用此文件的调试环境。
在菜单命令 File->Symbol path... 打开对话框,选择浏览,找到dmp文件所在目录相关的程序文件目录 E:\AppServer ,该目录下面有程序相关的 exe,pdb 文件。

输入下面的命令:

0:000> .sympath+ c:\symbols
Symbol search path is: E:\AppServer;c:\symbols
Expanded Symbol search path is: e:\appserver;c:\symbols
Error: Attempts to access 'c:\symbols' failed: 0x2 - 系统找不到指定的文件。

************* Symbol Path validation summary **************
Response                         Time (ms)     Location
OK                                             E:\AppServer
Error 
复制代码
这里不用管,这个文件夹后面可以生成。

0:000> .symfix
0:000> .symfix+ c:\symbols
0:000> .sympath
Symbol search path is: srv*
Expanded Symbol search path is: SRV*c:\symbols*http://msdl.microsoft.com/download/symbols

************* Symbol Path validation summary **************
Response                         Time (ms)     Location
Deferred  

这下对了。
执行下 reload命令:

0:000> .reload
................................................................
................................................................
............
接着执行下面:


0:000> .loadby sos clr
0:000> !tp
The version of SOS does not match the version of CLR you are debugging.  Please
load the matching version of SOS for the version of CLR you are debugging.
CLR Version: 4.0.30319.296
SOS Version: 4.6.96.0
Failed to load data access DLL, 0x80004005

这里提示说SOS的版本更CLR不匹配,这里需要找到当时生成Dump文件所在的服务器上的 sos.dll,注意,因为服务器程序是64位的,所以必须在 .Net Framework64 目录去找,同时把 mscordacwks.dll 文件一起拷贝过来(先暂时不用,下面马上会讲到)。

刚才这个命令执行后,我们惊喜的发现,c:\symbols 目录自己创建了,并且下载了 clr.pdb等几个目录,这是再将刚才服务器上拷贝的 sos.dll, mscordacwks.dll ,放到本地机器的 c:\symbols 目录下面。

再次执行这几个命令:

0:000> .reload
................................................................
................................................................
............
0:000> .loadby sos clr
0:000> !tp
The version of SOS does not match the version of CLR you are debugging.  Please
load the matching version of SOS for the version of CLR you are debugging.
CLR Version: 4.0.30319.296
SOS Version: 4.6.96.0
Failed to load data access DLL, 0x80004005

还是报错,看来 sos.dll 没有加载正确,用下面的命令:

0:000> .load c:\symbols\sos.dll
0:000> .loadby sos clr
0:000> !tp
这里load命令必须带SOS.dll的路径。加载了它,然后执行 .loadby sos clr ,表示调试.NET托管程序。

开始漫长的等待,程序窗口提示:

*BUSY*
Downloading symbols for [clr.pdb] /

等到相关的符号文件全部下载完毕,终于出现了久违的成功界面:

CPU utilization: 11%
Worker Thread: Total: 8 Running: 0 Idle: 8 MaxLimit: 32767 MinLimit: 8
Work Request in Queue: 0
--------------------------------------
Number of Timers: 14
--------------------------------------
Completion Port Thread:Total: 1 Free: 1 MaxFree: 16 CurrentLimit: 0 MaxLimit: 1000 MinLimit: 8

4,获取帮助信息

有关WinDbg详细的调试命名,可以参考下面文章:
windbg调试命令 
http://www.cnblogs.com/kekec/archive/2012/12/02/2798020.html

或者,你也可以随时用帮助,查看如何使用:

0:000> !help
-------------------------------------------------------------------------------
SOS is a debugger extension DLL designed to aid in the debugging of managed
programs. Functions are listed by category, then roughly in order of
importance. Shortcut names for popular functions are listed in parenthesis.
Type "!help <functionname>" for detailed info on that function. 

Object Inspection                  Examining code and stacks
-----------------------------      -----------------------------
DumpObj (do)                       Threads
DumpArray (da)                     ThreadState
DumpStackObjects (dso)             IP2MD
DumpHeap                           U
DumpVC                             DumpStack
GCRoot                             EEStack
ObjSize                            CLRStack
FinalizeQueue                      GCInfo
PrintException (pe)                EHInfo
TraverseHeap                       BPMD 
                                   COMState

Examining CLR data structures      Diagnostic Utilities
-----------------------------      -----------------------------
DumpDomain                         VerifyHeap
EEHeap                             VerifyObj
Name2EE                            FindRoots
SyncBlk                            HeapStat
DumpMT                             GCWhere
DumpClass                          ListNearObj (lno)
DumpMD                             GCHandles
Token2EE                           GCHandleLeaks
EEVersion                          FinalizeQueue (fq)
DumpModule                         FindAppDomain
ThreadPool                         SaveModule
DumpAssembly                       ProcInfo 
DumpSigElem                        StopOnException (soe)
DumpRuntimeTypes                   DumpLog
DumpSig                            VMMap
RCWCleanupList                     VMStat
DumpIL                             MinidumpMode 
                                   AnalyzeOOM (ao)

Examining the GC history           Other
-----------------------------      -----------------------------
HistInit                           FAQ
HistRoot
HistObj
HistObjFind
HistClear
复制代码
也可以使用 .help命令,这个不一样,这里列出部分命令:

0:000> .help
. commands:
   .allow_exec_cmds [0|1] - control execution commands
   .allow_image_mapping [0|1] - control on-demand image file mapping
   .apply_dbp [<options>] - add current data breakpoint state to a
                            register context
   .asm [<options>] - set disassembly options
   .asm- [<options>] - clear disassembly options
   .attach <proc> - attach to <proc> at next execution
   .block { <commands> } - brackets a set of commands for nested execution
   .break - break out of the enclosing loop

也可使用.hh命令:
 Use ".hh <command>" or open debugger.chm in the debuggers directory to get
detailed documentation on a command.

OK,有了dump文件生成,调试环境配置,还有帮助命令,现在总算是入门了。
========

Windows调试学习笔记:(二)WinDBG调试.NET程序示例

http://www.cnblogs.com/ceachy/p/WinDBG_Demo1.html

  好不容易把环境打好了,一定要试试牛刀。我创建了一个极其简单的程序(如下)。

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication1{    class Program    {        static void Main(string[] args)        {            int a;            string str;            a = 5;            str = a.ToString();            Console.WriteLine(str);        }    }}


默认编译成x86的输出代码,路径是E:\Projects\Practise\ConsoleApplication1\ConsoleApplication1\bin\Debug。然后就开始调试的步骤了:

  1、加载调试程序

  启动WinDBG以后,选择“文件-选择可执行文件。。。”,找到E:\Projects\Practise\ConsoleApplication1\ConsoleApplication1\bin\Debug目录下的ConsoleApplication1.exe文件,单击“打开”按钮。这样我们的调试目标程序已经打开了。

  2、加载pdb文件

  执行ld命令为ConsoleApplication1.exe程序集加载pdb文件:

0:000> ld ConsoleApplication1
*** WARNING: Unable to verify checksum for ConsoleApplication1.exe
Symbols loaded for ConsoleApplication1
  3、加载SOS

基于以往失败经验,我们一开始就使用SXE命令:

0:000> sxe ld:clrjit
0:000> g
...
0:000> .loadby sos clr
  4、设置断点

我们是用BPMD命令设置断点如下:

0:000> !bpmd ConsoleApplication1.exe ConsoleApplication1.Program.Main
Found 1 methods in module 00162ea4...
MethodDesc = 001637f8
Adding pending breakpoints...
  5、检查断点是否停下来

输入g让被调试程序继续执行,如果在断点位置停下来了,就会显示如下结果:

0:000> g
(6164.4fe0): CLR notification exception - code e0444143 (first chance)
JITTED ConsoleApplication1!ConsoleApplication1.Program.Main(System.String[])
Setting breakpoint: bp 00210070 [ConsoleApplication1.Program.Main(System.String[])]
Breakpoint 0 hit
eax=001637f8 ebx=00000000 ecx=0265ba00 edx=0035f150 esi=0060c7e0 edi=0035f0a0
eip=00210070 esp=0035f078 ebp=0035f084 iopl=0         nv up ei pl nz ac pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000216
00210070 55              push    ebp

  6、检查堆栈

使用!clrstack命令检查堆栈,记得加上-a参数:

0:000> !clrstack -a
OS Thread Id: 0x4fe0 (0)
Child SP IP       Call Site
0035f078 00210070 ConsoleApplication1.Program.Main(System.String[]) [E:\Projects\Practise\ConsoleApplication1\ConsoleApplication1\Program.cs @ 11]
    PARAMETERS:
        args (<CLR reg>) = 0x0265ba00
    LOCALS:
        <no data>
        <no data>

0035f2a0 5dc321bb [GCFrame: 0035f2a0] 

这里已经能够看到Main函数内部的一些情况了,比如args的地址。但是我们想看的a和str却还没有。这又两个原因:1、它们不会显示名字;2、它们还没有被定义。

  7、单步执行

不断输入p命令往下执行,并且不断地检查堆栈情况。我输入9次以后出现了以下结果:

0:000> p
eax=00000000 ebx=00000000 ecx=0265ba00 edx=00000000 esi=0060c7e0 edi=0035f0a0
eip=00210091 esp=0035f064 ebp=0035f074 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
00210091 90              nop
0:000> !clrstack -a
OS Thread Id: 0x4fe0 (0)
Child SP IP       Call Site
0035f064 00210091 ConsoleApplication1.Program.Main(System.String[]) [E:\Projects\Practise\ConsoleApplication1\ConsoleApplication1\Program.cs @ 11]
    PARAMETERS:
        args (0x0035f070) = 0x0265ba00
    LOCALS:
        0x0035f06c = 0x00000000
        0x0035f068 = 0x00000000

0035f2a0 5dc321bb [GCFrame: 0035f2a0] 

这里LOCALS:下面的两个就是a和str,但是它们下载还是没有值。又执行2次p命令以后,a的值已经显示出来了:

0:000> !clrstack -a
OS Thread Id: 0x4fe0 (0)
Child SP IP       Call Site
0035f064 00210099 ConsoleApplication1.Program.Main(System.String[]) [E:\Projects\Practise\ConsoleApplication1\ConsoleApplication1\Program.cs @ 16]
    PARAMETERS:
        args (0x0035f070) = 0x0265ba00
    LOCALS:
        0x0035f06c = 0x00000005
        0x0035f068 = 0x00000000

0035f2a0 5dc321bb [GCFrame: 0035f2a0] 

继续执行5次p命令之后,str的地址也显示出来了:

0:000> !clrstack -a
OS Thread Id: 0x4fe0 (0)
Child SP IP       Call Site
0035f064 002100aa ConsoleApplication1.Program.Main(System.String[]) [E:\Projects\Practise\ConsoleApplication1\ConsoleApplication1\Program.cs @ 18]
    PARAMETERS:
        args (0x0035f070) = 0x0265ba00
    LOCALS:
        0x0035f06c = 0x00000005
        0x0035f068 = 0x0265c06c

0035f2a0 5dc321bb [GCFrame: 0035f2a0] 

  8、查看引用类型成员

str的地址显示出来以后,我们就可以使用!dumpobj命令来查看它的值以及其他信息了:

0:000> !dumpobj 0x0265c06c
Name:        System.String
MethodTable: 5d17fba0
EEClass:     5ceb8bb0
Size:        16(0x10) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String:      5
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
5d182b6c  4000103        4         System.Int32  1 instance        1 m_stringLength
5d181fbc  4000104        8          System.Char  1 instance       35 m_firstChar
5d17fba0  4000105        8        System.String  0   shared   static Empty
    >> Domain:Value  005d4d00:02651228 <<

从中我们看到字符串的值为"5",它的长度是1等等。

总结:

  这里记录的过于详细了。
========
0 0
原创粉丝点击