How to identify array type?

前端 未结 1 2047
说谎
说谎 2020-12-17 23:25

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 situat

相关标签:
1条回答
  • 2020-12-17 23:47

    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 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] 
    

    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
    

    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
    

    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();
    }
    

    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:

    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
    ...
    

    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
    ...
    

    As you can see, ecx gets 732a30e2, which somehow maps to the type information for System.Single, but I can't figure out how...

    0 讨论(0)
提交回复
热议问题