Memory 如何在C#托管代码中重新创建SOS.dll功能?SOS.dll ObjSize和DumpObject在后台是如何工作的?

Memory 如何在C#托管代码中重新创建SOS.dll功能?SOS.dll ObjSize和DumpObject在后台是如何工作的?,memory,reflection,clr,sos,Memory,Reflection,Clr,Sos,我在这个问题上做了很多研究,但仍然感到困惑。我以前曾向stackOverflow提出过这个问题,但得到的答复不太令人满意。这让我相信这是一个相当高级的话题,需要对CLR有深刻的理解才能回答。我希望一位大师能帮助我 这个问题很大程度上是基于我以前的文章和发现 我正在尝试使用反射重新创建SOS.dll的一些功能。特别是ObjSize和DumpObject命令。我使用反射查找所有字段,然后如果字段是基本类型,我将基本类型的大小添加到对象的总体大小中。如果字段是值类型,那么我递归调用原始方法并沿着引用树

我在这个问题上做了很多研究,但仍然感到困惑。我以前曾向stackOverflow提出过这个问题,但得到的答复不太令人满意。这让我相信这是一个相当高级的话题,需要对CLR有深刻的理解才能回答。我希望一位大师能帮助我

这个问题很大程度上是基于我以前的文章和发现

我正在尝试使用反射重新创建SOS.dll的一些功能。特别是
ObjSize
DumpObject
命令。我使用反射查找所有字段,然后如果字段是基本类型,我将基本类型的大小添加到对象的总体大小中。如果字段是值类型,那么我递归调用原始方法并沿着引用树遍历,直到找到所有基本类型字段

我一直得到比
SOS.dll ObjSize
命令大两倍左右的对象大小。我发现的一个原因是我的反射代码似乎正在查找SOS忽略的字段。例如,在字典中,SOS查找的字段如下:

  • 水桶
  • 条目
  • 计数
  • 版本
  • 自由列表
  • 免费计数
  • 比较器
  • 钥匙
  • 价值观
  • _同步根
  • 缪斯信息
但是,我的反射代码可以找到上述所有内容,还可以找到:

  • 版本名
  • 哈西塞纳
  • KeyValuePairsName
  • 比较名称
先前的回答暗示这些是常量而不是字段。常量不在内存中吗?我应该忽略常量吗?我不确定要使用哪些绑定标志来获取除常量以外的所有字段

此外,我对SOS ObjSize和DumpObject命令中发现的不一致性感到困惑。我知道DumpObject不会查看引用类型的大小。但是,当我在上面提到的字典中调用对象大小时,我得到:

  • 字典-532B
然后我调用字典上的DumpObject来获取它的引用类型的内存地址。然后,当我对其引用类型调用Objsize时,我得到:

  • 水桶-40
  • 参赛作品-364
  • 比较器-12
  • 钥匙-492
  • (其余为空或基本)
**顶级字典上的ObjSize不应该大致是字典中所有字段上的ObjSize的总和吗?为什么反射会找到更多转储对象的字段?有没有想过为什么我的反射分析返回的数字大于SOS.dll**

此外,我在上面链接的帖子中提出的一个问题也没有得到答案。我在问在计算对象的内存大小时是否应该忽略属性。普遍的共识是忽略它们。但是,我发现了一个很好的例子,说明从Type.GetFields()返回的集合中何时不包括属性的支持字段。在细绳罩下观察时,您会发现:

  • 对象包含名为FirstChar的属性
  • 对象包含名为Chars的属性
  • 对象包含名为Length的属性
  • 对象包含名为m_stringLength的字段
  • 对象包含名为m_firstChar的字段
  • 对象包含名为空的字段
  • 对象包含名为TrimHead的字段
  • 对象包含名为TrimTail的字段
  • 对象包含名为TrimBoth的字段
  • 对象包含名为charPtrAlignConst的字段
  • 对象包含名为alignConst的字段
m_firstChar和m_stringLength是属性firstChar和Length的支持字段,但字符串的实际内容保存在Chars属性中。这是一个索引属性,可以对其进行索引以返回字符串中的所有字符,但我找不到包含字符串字符的对应字段


有什么想法吗?或者如何获取索引属性的支持字段?索引属性是否应该包含在内存大小中?

虽然这个想法很有趣,但我认为它最终是徒劳的,因为反射不能提供对对象实际存储的访问。反射允许查询类型,但不能查询它们的实际内存表示(这是CLR的一个实现细节)

对于引用类型,CLR本身向每个实例(MT和syncblk)添加内部字段。反射API不会显示这些内容。此外,CLR可以根据类型的定义对字段的存储使用任何类型的填充/压缩。这意味着原语类型的大小在不同的引用类型之间可能不一致。反射也不允许你发现这一点

简言之,反射无法发现产生正确结果所需的许多细节

你问了完全相同的问题。你到底为什么认为你会得到不同的答案?