Search code examples
c#stringmemoryallocation

Allocation for strings - Visual studio memory profiler doesn't make sense


Visual studio memory profiler doesn't make sense to me, I'm looking at a double string array [10,1000] and trying to figure out how is the memory allocated for it.

  1. How does the "e96" string takes 20 bytes? shouldn't it be: length member(size of int) + string length * size of char? so in this case 4 + 3*2 = 10 bytes

My calculation is based on sizeof string question and Majid answer here

  1. the snapshot below is sorted so the minimum string size at the array is 20 bytes, how is the total size = 40KB? it should be > 10,000 * 20

What am I missing?

this is the snapshot taken from the heap of the double string array

Code can be found here

string[,] mat = GetData(); // memory allocation is done here.

Solution

  • Answering your second question first:

    Please try to take a snapshot before this line:

    string[,] mat = GetData();
    
    Console.WriteLine("Please take a snapshot here!");
    Console.ReadLine()
    
    object cellObjectList = GetCells(mat);
    

    You are taking the snapshot where the mat[,] is probably being optimized away. See the inclusive size of your array in a snapshot taken at this point.

    To answer your first question:

    By debugging and seeing the string [,] memory,

    The first string (which is e96) points to this address:

    a0 6e c1 02 (0x02c1e6a0)
    

    By examining this address we see these 20 bytes.

    84 d4 ad 70 03 00 00 00 65 00 39 00 36 00 00 00 00 00 00 00
    

    The first four and the last zero bytes don't make sense?

    In a dump file, !DumpObject on the first string element 0x028923f0 shows:

    0:000> !do 028923f0
    Name:        System.String
    MethodTable: 70add484
    EEClass:     706b4a50
    Size:        20(0x14) bytes
    File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
    String:      e96
    Fields:
          MT    Field   Offset                 Type VT     Attr    Value Name
    70adf2d8  4000273        4         System.Int32  1 instance        3 m_stringLength
    70addecc  4000274        8          System.Char  1 instance       65 m_firstChar
    70add484  4000278       50        System.String  0   shared   static Empty
        >> Domain:Value  00c33988:NotInit  <<
    

    So our string should be 14 bytes? (4 bytes method table, 4 bytes string length, 3 x 2 = 6 for 3 unicode chars)

    But! a string is a link type, so first four bytes contain SyncBlockIndex (starting from address - 4)

    By dumping the memory at (0x028923f0 - 4) = 0x028923ec

    Now let's take the 20 bytes which we retrieved from the memory window

    // e96
    00 00 00 80 => SyncBlock for String type
    84 d4 ad 70 => Method Table of String class
    03 00 00 00 => Number of characters in string (string length = 3)
    65 00 => e
    39 00 => 9
    36 00 => 6
    00 00 => Padding it to the nearest 4 bytes, 16 here (excluding sync block)
    

    And we have 20 bytes.

    Hope this helps.