利用windbg调试class type,value type以及MethodTable等强化C#的基本概念

本文通过windbg调试一个简单的程序,来清除说明.Net framework中class type,value type的内存分配方式的不同,以及object内部的重要组成MethodTable的作用

用于说明问题的source code如下:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Collections;
 6 
 7 namespace VSDebug
 8 {
 9     class StringHolder
10     {
11         public string StringData;
12         public StringHolder(string stringData)
13         {
14             StringData = stringData;
15         }
16     } 
17 
18     class  TestClass
19     {
20         public ArrayList Holders;
21         [STAThread]
22         static void Main(string[] args)
23         {
24             TestClass testClass = new TestClass();
25             TestClass testClass1 = new TestClass();
26             testClass.Holders = new ArrayList();
27             for (int i = 0; i < 10++i)
28             {
29                 testClass.Holders.Add(new StringHolder("Hello"));
30             }
31             Console.ReadLine();
32         } 
33 
34     }
35 }
36 

设置project 的debug属性为enabled unmanaged code debugging,在31行设置breakpoint,然后press F5开始调试,并打开intermediate window开始windbg sos 调试

.load sos

extension C:\Windows\Microsoft.NET\Framework\v2.0.50727\sos.dll loaded

!dumpheap -stat

PDB symbol for mscorwks.dll not loaded

total 2086 objects

Statistics:

MT Count TotalSize Class Name

79100f58 1 12 System.Security.Permissions.SecurityPermission

790fdc5c 1 20 System.Text.StringBuilder

79104368 1 24 System.Collections.ArrayList

790fcc48 1 24 System.Reflection.Assembly

0023304c 2 24 VSDebug.TestClass

790feba4 1 28 System.SharedStatics

790fd0f0 3 36 System.Object

790ff734 2 40 System.RuntimeType

79100e38 1 44 System.Security.FrameSecurityDescriptor

790ff120 1 44 System.AppDomainSetup

7912dd40 1 64 System.Char[]

79100a18 2 72 System.Security.PermissionSet

790fe17c 1 72 System.ExecutionEngineException

790fe0e0 1 72 System.StackOverflowException

790fe044 1 72 System.OutOfMemoryException

790fed00 1 100 System.AppDomain

003c7508 7 100 Free

002330cc 10 120 VSDebug.StringHolder

790fe284 2 144 System.Threading.ThreadAbortException

7912d8f8 9 8992 System.Object[]

790fd8c4 2037 129576 System.String

Total 2086 objects

下面对each column作简要说明:

MT-〉MethodTable. 首先说明MethodTable的作用。我们知道每种type可以有多个instance。在C++中,每个instance,其每个field可以享有独立的space,而对于type的method提供一个公共的method入口地址。也就是说不管多少个相同类型的instance,其都指向了同一个同一的函数入口地址。在这个函数入口地址描述表中记录了各个函数的入口地址。而MethodTable就有点类似的作用。自不过所有Assembly都是自描述的,因此我们可以从MethodTable中,可以知道相应的instance。因此通过相应的debug命令!dumpheap -mt MTAddress可以知道在MethodTable中相关联的所有instance了

Count ->某个特定MethodTable地址下相关联的objects的数目

TotalSize->所占空间

Class Name->object descriptive information

请看下面:

!dumpheap -mt 0023304c

Address MT Size

0286168c 0023304c 12

02861698 0023304c 12

total 2 objects

Statistics:

MT Count TotalSize Class Name

0023304c 2 24 VSDebug.TestClass

Total 2 objects

可以看出,在该MethodTable中关联的有2个objects,一个object address是:0286168c,而另外一个object address 是:02861698

在.net中,我们知道,对于class type的object,其object ref是占用stack上的空间,而 object ref则指向了GC heap上的空间。刚才我们已经知道在heap上有2个VsDebug.TestClass的object,并且其Heap Address也已给出。

下面看看在stack是否有相应的VsDebug.TestClass ref指向其object.

!dso

OS Thread Id: 0xed8 (3800)

ESP/REG Object Name

ecx 02861788 System.Object[]

0014eef0 028616a4 System.Collections.ArrayList

0014eef8 028617d8 VSDebug.StringHolder

0014f064 028616a4 System.Collections.ArrayList

0014f068 028617d8 VSDebug.StringHolder

0014f06c 0286168c VSDebug.TestClass

0014f074 02861788 System.Object[] (System.Object[])

0014f29c 02861698 VSDebug.TestClass

0014f2a4 02861660 System.Object[] (System.String[])

0014f2bc 02861660 System.Object[] (System.String[])

0014f394 02861660 System.Object[] (System.String[])

0014f53c 02861660 System.Object[] (System.String[])

0014f564 02861660 System.Object[] (System.String[])

果然,可以看到在stack上看到2个指向heap上的VsDebug.TestClass 类型的object :) 

原文地址:https://www.cnblogs.com/Winston/p/1340748.html