【问题标题】:Allocation for strings - Visual studio memory profiler doesn't make sense字符串分配 - Visual Studio 内存分析器没有意义
【发布时间】:2020-04-19 08:21:47
【问题描述】:

Visual Studio 内存分析器对我来说没有意义,我正在查看一个双字符串数组 [10,1000] 并试图弄清楚内存是如何分配给它的。

  1. “e96”字符串如何占用 20 个字节?不应该是:长度成员(int大小)+字符串长度*字符大小?所以在这种情况下 4 + 3*2 = 10 个字节

我的计算是基于 sizeof 字符串问题和 Majid 回答 here

  1. 下面的快照已排序,因此数组中的最小字符串大小为 20 字节,总大小 = 40KB 怎么算?它应该是 > 10,000 * 20

我错过了什么?

代码可以找到here

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

【问题讨论】:

  • 您对 1 的解释是 奇怪(20 似乎对我来说是正确的)...您在发布之前检查过有关该主题的任何文章吗?提供这样的链接将有助于了解您的想法来自哪里。还显示产生该结果的代码会有所帮助...(我假设您已经看到类似 stackoverflow.com/questions/26998758/… 的内容)
  • 您的数组中的字符串可能指向实习字符串(您是否通过分配“e96”来设置数组的所有元素?)
  • 不,数组由不同长度的随机字符串填充
  • 一个字符是一个类,所以类中有标题信息。该类还包含一个私有属性来指示 char 是一个字节还是两个字节。
  • @jdweng C# char 是一个结构体,总是两个字节

标签: c# string memory allocation


【解决方案1】:

先回答你的第二个问题:

请尝试在此行之前拍摄快照:

string[,] mat = GetData();

Console.WriteLine("Please take a snapshot here!");
Console.ReadLine()

object cellObjectList = GetCells(mat);

您正在拍摄 mat[,] 可能被优化掉的快照。在此时拍摄的快照中查看阵列的包含大小。

回答你的第一个问题:

通过调试看到字符串[,]内存,

第一个字符串(e96)指向这个地址:

a0 6e c1 02 (0x02c1e6a0)

通过检查这个地址,我们看到了这 20 个字节。

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

前四个和最后一个零字节没有意义?

在转储文件中,第一个字符串元素 0x028923f0 上的 !DumpObject 显示:

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

所以我们的字符串应该是 14 字节? (4 字节方法表,4 字节字符串长度,3 x 2 = 6 用于 3 个 unicode 字符)

但是!字符串是链接类型,所以前四个字节包含 SyncBlockIndex(从地址 - 4 开始)

通过在 (0x028923f0 - 4) = 0x028923ec 处转储内存

现在让我们从内存窗口中取出 20 个字节

// 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)

我们有 20 个字节。

希望这会有所帮助。

【讨论】:

  • 显然,我没有考虑对象标头开销。谢谢
猜你喜欢
  • 2011-03-22
  • 1970-01-01
  • 2021-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-27
  • 2020-01-29
  • 2015-09-12
相关资源
最近更新 更多