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
...
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.)
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.
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?
One way to do it is to dump the IL corresponding to the method that the array is being created in.
First, use
!clrstack
to get the method you're in. In my case I'm in a dummy app in theMain
method:Next use
!name2ee
to get the method desc of this method (the next command needs it):Now, dump the IL of the method:
For comparison, this is my method in C#:
You can see on line IL_000f that a new array of type
System.Single
is being created.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: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 intoecx
andedx
, respectively:As you can see,
ecx
gets732a30e2
, which somehow maps to the type information forSystem.Single
, but I can't figure out how...