如何识别数组类型? [英] How to identify array type?
问题描述
我有一个OutOfMemoryException,我想分析的大小和它应创建的阵列的类型。
I have an OutOfMemoryException and I'd like to analyze the size and the type of the array which shall be created.
我创建了一个演示的目的转储这种情况下,我能得到以下信息:
I have created a demo purpose dump for that situation and I'm able to get the following information:
0:000> !pe
Exception object: 023f389c
Exception type: System.OutOfMemoryException
Message: <none>
InnerException: <none>
StackTrace (generated):
SP IP Function
0015EE44 0099007F OOM2!OOM2.Program.Main()+0xf
StackTraceString: <none>
HResult: 8007000e
0:000> !u 0099007F
Normal JIT generated code
OOM2.Program.Main()
Begin 00990070, size 22
00990070 baffffff7f mov edx,7FFFFFFFh
00990075 b90241a478 mov ecx,offset mscorlib_ni+0x4102 (78a44102)
0099007a e8192194ff call 002d2198 (JitHelp: CORINFO_HELP_NEWARR_1_VC)
>>> 0099007f 8bc8 mov ecx,eax
...
所以,我可以看到,创建一个新的阵列和大小7FFFFFFF,也就是2十亿的项目。 (请忽视的事实是,你甚至不能在32位.NET应用程序创建一个大小的一个byte [],所以在这个例子中,类型可能不会在所有问题。)
So I can see that a new array is created and the size is 7FFFFFFF, which is 2 billion items. (Please ignore the fact that you can't even create a byte[] of that size in a 32 bit .NET application, so in this example the type would probably not matter at all.)
我现在已经读了数组的类型是ECX寄存器,但不幸的是 mscorlib_ni + 0x4102(78a44102)
是不是非常有帮助。
I have now read that the type of the array is in the ECX register, but unfortunately mscorlib_ni+0x4102 (78a44102)
isn't very helpful.
我已经试过!万
,!MDT
,甚至不切实际!ip2mt
,但它们都没有显示预期的字节
或字节[]
输出。有来自mscorlib中的那个原生图像获取的类型的方法是什么?
I have tried !mln
, !mdt
and even unrealistic !ip2mt
, but none of them displays the expected byte
or byte[]
output. Is there a way of getting the type from that native image of mscorlib?
推荐答案
要做到这一点是转储IL对应于数组正在创建的方法,一种方法
One way to do it is to dump the IL corresponding to the method that the array is being created in.
首先,使用!clrstack
来让你的方法。以我为例,我在主<一个虚拟应用程序/ code>方法:
First, use !clrstack
to get the method you're in. In my case I'm in a dummy app in the Main
method:
0:000> !clrstack
OS Thread Id: 0x7d0 (0)
Child SP IP Call Site
0016f094 758dc42d [HelperMethodFrame: 0016f094]
0016f120 003200af ConsoleApplication4.Program.Main(System.String[]) [c:\Users\smt\Documents\Visual Studio 2012\Projects\ConsoleApplication4\Program.cs @ 215]
0016f2bc 743b3de2 [GCFrame: 0016f2bc]
接下来使用 name2ee
来获得这种方法的方法说明(下一个命令需要它):
Next use !name2ee
to get the method desc of this method (the next command needs it):
0:000> !name2ee ConsoleApplication4!ConsoleApplication4.Program.Main
Module: 00282eac
Assembly: ConsoleApplication4.exe
Token: 0600013c
MethodDesc: 00283dbc
Name: ConsoleApplication4.Program.Main(System.String[])
JITTED Code Address: 00320050
现在,转储方法的IL:
Now, dump the IL of the method:
0:000> !dumpil 00283dbc
ilAddr = 002d4bc4
IL_0000: nop
IL_0001: newobj class [mscorlib]System.Collections.Generic.List`1<?????? ??????n?.::.ctor
IL_0006: stloc.0
IL_0007: br.s IL_001e
IL_0009: nop
IL_000a: ldc.i4 2147483647
IL_000f: newarr System.Single
IL_0014: stloc.1
IL_0015: ldloc.0
IL_0016: ldloc.1
IL_0017: callvirt class [mscorlib]System.Collections.Generic.List`1<?????? ??????N?.::Add
IL_001c: nop
IL_001d: nop
IL_001e: ldc.i4.1
IL_001f: stloc.2
IL_0020: br.s IL_0109
为了便于比较,这是我在C#中的方法:
For comparison, this is my method in C#:
static void Main(string[] args)
{
List<float[]> arrays = new List<float[]>();
while (true)
{
float[] f = new float[Int32.MaxValue];
arrays.Add(f);
}
Console.ReadKey();
}
您可以在线IL_000f该类型的新数组 System.Single
正在创建看到的。
You can see on line IL_000f that a new array of type System.Single
is being created.
我就沿着这条道路,因为我无法破译的参数被传递到创建数组实际的本地方法。如果您运行 KB
在点抛出异常:
I went down this road because I can't decipher the argument being passed to the actual native method that creates the array. If you run kb
at the point the exception is thrown:
0:000> kb
ChildEBP RetAddr Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
0016efa4 74502a42 e0434352 00000001 00000005 KERNELBASE!RaiseException+0x58
0016f048 745d55ef 00000000 bc1d0b3d 0016f10c clr!RaiseTheExceptionInternalOnly+0x276
0016f078 7464ae51 bc1d0a7d 0016f150 00000000 clr!UnwindAndContinueRethrowHelperAfterCatch+0x83
0016f118 003200af 00000000 02202480 00000000 clr!JIT_NewArr1+0x1af
0016f138 743b3de2 00720198 0016f198 743c3315 0x3200af
0016f144 743c3315 0016f1dc 0016f188 74502c66 clr!CallDescrWorkerInternal+0x34
...
您可以看到 CLR!JIT_NewArr1
被调用,它创建了一个一维数组。为了做到这一点,它需要的类型和大小的。这些参数将被复制到 ECX
和 EDX
,分别为:
You can see that clr!JIT_NewArr1
is being called, which creates a one-dimensional array. To do that, it needs the type and the size. These arguments are copied into ecx
and edx
, respectively:
0:000> !u 003200AF
...
003200a0 b9e2302a73 mov ecx,offset mscorlib_ni+0x30e2 (732a30e2)
003200a5 baffffff7f mov edx,7FFFFFFFh
003200aa e89121f5ff call 00272240 (JitHelp: CORINFO_HELP_NEWARR_1_VC)
>>> 003200af 8945e8 mov dword ptr [ebp-18h],eax
003200b2 8b45e8 mov eax,dword ptr [ebp-18h]
003200b5 8945f0 mov dword ptr [ebp-10h],eax
...
正如你所看到的, ECX
获得 732a30e2
,这在某种程度上映射到的类型信息 System.Single
,但我不知道如何...
As you can see, ecx
gets 732a30e2
, which somehow maps to the type information for System.Single
, but I can't figure out how...
这篇关于如何识别数组类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!