上篇随笔提出“如何查看数组中各个元素”的问题,没解决,今天继续搜索,看到有人介绍用dd命令查看,原文是英文,现翻译如下。
原文: Arrays and SOS
注意:这是在X86上调试的,如果是在IA64/AMD64上调试,数组的格式会有些许区别(比如内存地址将会是64位而不是文章中的32位)。
预备工作:创建三个数组
string[] strs = new string[] { "String 1", "String 2", "String 3" };
int[] ints = new int[] { 21, 22, 23, 24, 25, 26, 27 };
double[] fps = new double[] { 3.14 };
首先,用 !sos.dso命令获取这些数组的地址
0:000> !sos.dso(自语:数组元素是值类型(自定义的结构体)的场合,输出的都是该类型的数组形式,如System.Double[];元素是引用类型的场合,则以 System.Object[]形式出现。)
接着,用!do命令获取该数组的类型信息
0:000> !do 00ac2aa4
Name: System.Int32[]
MethodTable: 5b9ca974
EEClass: 5ba4d4ec
Size: 40(0x28) bytes
Array: Rank 1, Type Int32
Element Type: System.Int32
Fields:
None
OK,这是Int32型的数组,每个子元素占4字节。由于!do只能查看数组对象本身的信息,不能深入到其子元素,所以这里用到dd命令
0:000> dd 00ac2aa4
00ac2aa4 5b9ca974 00000007 00000015 00000016
00ac2ab4 00000017 00000018 00000019 0000001a
00ac2ac4 0000001b 00010000 5b9938b0 00000000
00ac2ad4 00010000 5b9c9b18 00000001 51eb851f
00ac2ae4 40091eb8 00010000 5b9b2be0 00000006
00ac2af4 00000000 00000080 00010000 5b9c6614
00ac2b04 00000001 5b9938b0 00ac2aec 00010000
00ac2b14 5b9b2c8c 00000080 00010000 5b9b413c
首列是序号,显示的是该行起始的内存地址,可以看出,每行16字节,一列4字节。
着重说下高亮显示的那几条数据。绿色的那条是该数组的方法表,如果之前没用!do命令查看数组信息的话,可以用!dumpmt命令查看一下
0:000> !dumpmt 5b9ca974
EEClass: 5ba4d4ec
Module: 5b918000
Name: System.Int32[]
mdToken: 02000000 (C:"WINNT"Microsoft.NET"Framework"v2.0.40428"assembly"GAC_32"mscorlib"2.0.3600.0__b77a5c561934e089"mscorlib.dll)
BaseSize: 0xc
ComponentSize: 0x4
Number of IFaces in IFaceMap: 4
Slots in VTable: 25
黄色的这条告诉我们这个数组有多少子元素,这里显示的是7个,Int32是4字节(一个Int32用一列表示),黄条后面的7个红条条保存的就是该数组7个子元素的值(21-27)。
*这里的数值是用16进制表示,所以15对应的是十进制的21。
然后,我们分析double[]型的。一个double占8字节(一个Double需要二列表示)。
0:000> dd 00ac2ad8
00ac2ad8 5b9c9b18 00000001 40091eb8 51eb851f
00ac2ae8 00010000 5b9b2be0 00000006 00000000
00ac2af8 00000080 00010000 5b9c6614 00000001
00ac2b08 5b9938b0 00ac2aec 00010000 5b9b2c8c
00ac2b18 00000080 00010000 5b9b413c 00ac2b80
00ac2b28 00010100 00000000 00010000 5b9b4668
00ac2b38 00000000 00000009 0000000a 00010000
00ac2b48 5b9c6614 0000000a 5b9938b0 00000000
老样子,绿条条是该数组的方法表,黄条条表示该数组只有1个子元素。前面也说了,是double型的,要8字节,需要2列合起来表示一个double。
0X40091eb851eb851f,反正我是看不出这个值是多少,借助命令.formats
0:000> .formats 40091eb851eb851f Evaluate expression:
Hex: 40091eb8`51eb851f
Decimal: 4614253070214989087
Octal: 0400110753412172702437
Binary: 01000000 00001001 00011110 10111000 01010001 11101011 10000101 00011111
Chars: @...Q...
Time: Fri Dec 27 09:23:41.498 16222 (GMT-7)
Float: low 1.26444e+011 high 2.1425
Double: 3.14
结果出来了,3.14。
最后,分析object[]。老样子,dd
0:000> dd 00ac2a88
00ac2a88 5b9c6614 00000003 5b99452c 00ac2a1c
00ac2a98 00ac2a40 00ac2a64 00010000 5b9ca974
00ac2aa8 00000007 00000015 00000016 00000017
00ac2ab8 00000018 00000019 0000001a 0000001b
00ac2ac8 00010000 5b9938b0 00000000 00010000
00ac2ad8 5b9c9b18 00000001 51eb851f 40091eb8
00ac2ae8 00010000 5b9b2be0 00000006 00000000
00ac2af8 00000080 00010000 5b9c6614 00000001
这个数组有3个子元素。这里有个问题,到目前为止只知道这是个object,具体什么类型一无所知,天无绝人之路,紫条条的就是元素的方法表(与绿条条object的方法表不同)。接着就用!dumpmt查看该元素的类型。
0:000> !dumpmt 5b99452c
EEClass: 5b9d7f10
Module: 5b918000
Name: System.String
mdToken: 02000027 (C:"WINNT"Microsoft.NET"Framework"v2.0.40428"assembly"GAC_32"mscorlib"2.0.3600.0__b77a5c561934e089"mscorlib.dll)
BaseSize: 0x10
ComponentSize: 0x2
Number of IFaces in IFaceMap: 5
Slots in VTable: 190
很明显,这是String型的。由于是string型的,后面3个红条条保存的是内存地址,这里要用 !do命令查看具体的值了。
0:000> !do 00ac2a1c
Name: System.String
MethodTable: 5b99452c
EEClass: 5b9d7f10
Size: 34(0x22) bytes
(C:"WINNT"Microsoft.NET"Framework"v2.0.40428"assembly"GAC_32"mscorlib"2.0.3600.0__b77a5c561934e089"mscorlib.dll)
String: String 1
0:000> !do 00ac2a40
Name: System.String
MethodTable: 5b99452c
EEClass: 5b9d7f10
Size: 34(0x22) bytes
(C:"WINNT"Microsoft.NET"Framework"v2.0.40428"assembly"GAC_32"mscorlib"2.0.3600.0__b77a5c561934e089"mscorlib.dll)
String: String 2
0:000> !do 00ac2a64
Name: System.String
MethodTable: 5b99452c
EEClass: 5b9d7f10
Size: 34(0x22) bytes
(C:"WINNT"Microsoft.NET"Framework"v2.0.40428"assembly"GAC_32"mscorlib"2.0.3600.0__b77a5c561934e089"mscorlib.dll)
String: String 3
如上所示,分别是String 1,String 2,String 3。
分析完毕,收工!