0

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.
Ofir
  • 517
  • 4
  • 16
  • Your explanation of 1 is *strange* (20 seem to be about right to me)... Did you check any article on the topic before posting? Providing such link would help to understand where you ideas are coming from. Also showing code that produced that result would help... (I assume you've seen something like https://stackoverflow.com/questions/26998758/why-is-typedreference-maketypedreference-so-constrained) – Alexei Levenkov Apr 19 '20 at 08:29
  • Your strings in your array probably point to interned strings (are you setting all the elements of your array by assigning "e96" ?) – Oguz Ozgul Apr 19 '20 at 09:45
  • no, array is populated by random strings with different length – Ofir Apr 19 '20 at 09:52
  • A character is a class so there are header info in the class. Also the class contains a private property to indicate if the char is one or two bytes. – jdweng Apr 19 '20 at 10:02
  • @jdweng C# char is a struct and is always two byted – David Heffernan Apr 20 '20 at 07:29

1 Answers1

1

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.

Oguz Ozgul
  • 6,809
  • 1
  • 14
  • 26