【问题标题】:Investigation of CLR via SOS通过 SOS 调查 CLR
【发布时间】:2014-06-22 11:20:31
【问题描述】:

目前我正在深入研究 CLR 并尝试找到我的托管对象的适当大小。

我有两种简单的类型:

XClass

    class XClass
{
    public XStruct StructField = new XStruct();
    public int IntField;
    public double DoubleField;
}

XStruct

struct XStruct
{
    public short ShortField;
    public long LongField;
}

还要考虑涉及此对象的代码 sn-p:

static unsafe void Main(string[] args)
{
    double angle = 0.34;

    {
        double anotherDouble = 1.49;

        XStruct xStruct = new XStruct();
        xStruct.ShortField = 12;
        xStruct.LongField = 1234567890;

        XClass classObject = new XClass();
        classObject.DoubleField = angle + anotherDouble;
        classObject.IntField = 123;
        classObject.StructField = xStruct;

        <<<<<<<<BREAKPOINT>>>>>>>

        xStruct.ShortField = 3;
    }

    double* ptr = &angle;

    Console.WriteLine(*(ptr - 1));
    Console.ReadKey();
}

所以,我尝试在堆栈中获取有关 XStruct 的一些信息,但在那里找不到。

!dso
PDB symbol for clr.dll not loaded
OS Thread Id: 0x1f94 (8084)
ESP/REG  Object   Name
0018EF1C 0260252c ConsoleApplication2.XClass
0018EF20 0260252c ConsoleApplication2.XClass
0018F290 0260252c ConsoleApplication2.XClass
0018F2C4 0260251c System.Object[]    (System.String[])
0018F2E0 0260252c ConsoleApplication2.XClass
0018F2E8 0260252c ConsoleApplication2.XClass
0018F30C 0260251c System.Object[]    (System.String[])
0018F3C0 0260251c System.Object[]    (System.String[])
0018F51C 0260251c System.Object[]    (System.String[])
0018F554 0260251c System.Object[]    (System.String[])
0018FA90 02601238 System.SharedStatics

请解释为什么不显示ConsoleApplication2.XStruct 以及为什么ConsoleApplication2.XClass 显示为堆栈中的对象。我认为 XClass (作为普通引用类型)应该放在堆中。或者可能是我对!dso 的理解不正确。

谢谢。

【问题讨论】:

  • 您可以查看元数据以了解对象大小。在这里你可以找到代码。 github.com/mumusan/dotnetex
  • @Dmitry Dovgopoly:我不是在寻找 XStruct 的大小。我对它为什么不显示为堆栈对象感兴趣。
  • 它也没有打印出你的双变量。显然,不打印值类型的本地变量。 msdn.microsoft.com/en-us/library/bb190764(v=vs.110).aspx
  • @usr 有没有办法打印值类型的本地变量? !dso 或其他参数的任何参数?

标签: c# .net clr


【解决方案1】:

!dso == 转储堆栈对象。关注“对象”,结构不是对象。

SOS 能够找到对象引用的唯一原因是它可以使用编译方法时抖动生成的元数据。垃圾收集器在执行堆栈遍历以查找对象引用时使用此数据。您可以在this answer 中阅读更多相关信息。此元数据中缺少值类型值,GC 不关心它们。

您可以通过创建它们的数组来推断结构的大小,给结构的第一个字段一个独特的值。用VS调试器查看数组,Debug + Windows + Memory + Memory1,把变量名放在Address字段。您将在数组标头之后将结构值返回到十六进制转储中。请注意,结构大小取决于 CLR 版本和进程的位数,因此只能将此信息用作提示。

【讨论】:

  • 有什么理由不只是使用sizeof(XStruct)
  • 当然,它不适用于任何具有引用类型字段的结构类型。
  • 两者都不是你的,因为你不能声明指向非托管类型的指针。
  • 没问题。有趣的是,如果结构包含其他值类型,您可以声明指向它们的指针并检查这些指针之间的间距,即使结构还包含引用类型。
  • @Hans Passant:我有更优雅的获取结构大小的方法是将结构声明为引用类型的字段,而不是使用 !dumpvc 来获取它的大小和其他信息。我真正感兴趣的是如何获取有关堆栈状态的信息,就像使用 !dso 作为引用类型一样。有什么办法让它工作吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多