字符串分配 - Visual studio 内存分析器没有意义
Allocation for strings - Visual studio memory profiler doesn't make sense
Visual studio 内存分析器对我来说没有意义,我正在查看双字符串数组 [10,1000]
并试图弄清楚如何为它分配内存。
- "e96" 字符串如何占用 20 个字节?不应该是:成员长度(int 的大小)+ 字符串长度 * char 的大小?所以在这种情况下 4 + 3*2 = 10 字节
我的计算是基于 sizeof string 问题和 Majid 答案 here
- 下面的快照已排序,因此数组中的最小字符串大小为 20 字节,总大小如何 = 40KB?它应该是 > 10,000 * 20
我错过了什么?
可以找到代码here
string[,] mat = GetData(); // memory allocation is done here.
先回答你的第二个问题:
请尝试在此行之前拍摄快照:
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 字节方法 table,4 字节字符串长度,3 x 2 = 6 用于 3 个 unicode 字符)
但是!字符串是 link 类型,因此前四个字节包含 SyncBlockIndex(从地址 - 4 开始)
通过将内存转储到 (0x028923f0 - 4) = 0x028923ec
现在让我们从内存中取出 20 个字节 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)
我们有 20 个字节。
希望这对您有所帮助。
Visual studio 内存分析器对我来说没有意义,我正在查看双字符串数组 [10,1000] 并试图弄清楚如何为它分配内存。
- "e96" 字符串如何占用 20 个字节?不应该是:成员长度(int 的大小)+ 字符串长度 * char 的大小?所以在这种情况下 4 + 3*2 = 10 字节
我的计算是基于 sizeof string 问题和 Majid 答案 here
- 下面的快照已排序,因此数组中的最小字符串大小为 20 字节,总大小如何 = 40KB?它应该是 > 10,000 * 20
我错过了什么?
可以找到代码here
string[,] mat = GetData(); // memory allocation is done here.
先回答你的第二个问题:
请尝试在此行之前拍摄快照:
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 字节方法 table,4 字节字符串长度,3 x 2 = 6 用于 3 个 unicode 字符)
但是!字符串是 link 类型,因此前四个字节包含 SyncBlockIndex(从地址 - 4 开始)
通过将内存转储到 (0x028923f0 - 4) = 0x028923ec
现在让我们从内存中取出 20 个字节 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)
我们有 20 个字节。
希望这对您有所帮助。