gpt4 book ai didi

c# - !DumpStackObjects 显示重复实例?

转载 作者:太空狗 更新时间:2023-10-29 23:03:51 24 4
gpt4 key购买 nike

我有一个小测试程序。当我查看主线程的堆栈对象时,它在那里显示了两次 MyClass 。知道为什么堆栈上有两个 MyClass 对象吗?

class Program  
{
struct MyStruct
{
int x;
int y;
}

class MyClass
{
int x;
int y;
}


static void Main(string[] args)
{
MyStruct s ;
MyClass c = new MyClass();
}
}
0:000> !DumpStackObjects  
OS Thread Id: 0xf74 (0)
RSP/REG Object Name
000000000023e9e8 00000000028f3c90 ConsoleApplication2.Program+MyClass
000000000023e9f8 00000000028f3c90 ConsoleApplication2.Program+MyClass
000000000023ea10 00000000028f3c70 System.Object[] (System.String[])
000000000023eb98 00000000028f3c70 System.Object[] (System.String[])
000000000023ed80 00000000028f3c70 System.Object[] (System.String[])
000000000023eda8 00000000028f3c70 System.Object[] (System.String[])

最佳答案

实际上它表明唯一的实例被引用了两次。请注意最左侧列中的值不同。它可以是指向同一实例的不同寄存器或堆栈帧的不同部分。

根据我的经验,这种情况经常发生(尤其是调试版本)。 !dso 对于定位对象很有用,在这种情况下,重要的列是对象列,它包含实际引用。

例如如果我从调试器运行上面的示例并在 Main 上放置一个断点,则 dso 的输出在 Main 方法返回之前看起来像这样。

0:000> !dso
OS Thread Id: 0x1944 (0)
ESP/REG Object Name
eax 0240b2e0 TestApp.Program+MyClass
ecx 0240b2e0 TestApp.Program+MyClass
0014F224 0240b2d0 System.Object[] (System.String[])
0014F3CC 0240b2d0 System.Object[] (System.String[])
0014F400 0240b2d0 System.Object[] (System.String[])

如您所见,eaxecx 寄存器都保存了对实例的引用,尽管 C# 源代码只有一个引用。

如果您查看 Main 的 JIT 编译代码,它看起来像这样

0:000> !u 00200070 
Normal JIT generated code
TestApp.Program.Main(System.String[])
Begin 00200070, size 46

C:\dev2010\TestApp\TestApp\Program.cs @ 33:
>>> 00200070 55 push ebp
00200071 8bec mov ebp,esp
00200073 83ec14 sub esp,14h
00200076 33c0 xor eax,eax
00200078 8945f4 mov dword ptr [ebp-0Ch],eax
0020007b 8945f8 mov dword ptr [ebp-8],eax
0020007e 894dfc mov dword ptr [ebp-4],ecx
00200081 833d3c31150000 cmp dword ptr ds:[15313Ch],0
00200088 7405 je 0020008f
0020008a e8c05ac268 call clr!JIT_DbgIsJustMyCode (68e25b4f)
0020008f 33d2 xor edx,edx
00200091 8955f0 mov dword ptr [ebp-10h],edx
00200094 90 nop

C:\dev2010\TestApp\TestApp\Program.cs @ 35:
00200095 b960391500 mov ecx,153960h (MT: TestApp.Program+MyClass)
0020009a e8811ff4ff call 00142020 (JitHelp: CORINFO_HELP_NEWSFAST)
0020009f 8945ec mov dword ptr [ebp-14h],eax
002000a2 8b4dec mov ecx,dword ptr [ebp-14h]
002000a5 ff158c391500 call dword ptr ds:[15398Ch] (TestApp.Program+MyClass..ctor(), mdToken: 06000003)
002000ab 8b45ec mov eax,dword ptr [ebp-14h]
002000ae 8945f0 mov dword ptr [ebp-10h],eax

C:\dev2010\TestApp\TestApp\Program.cs @ 36:
002000b1 90 nop
002000b2 8be5 mov esp,ebp
002000b4 5d pop ebp
002000b5 c3 ret

注意指令 call 00142020。这将创建 MyClass 的实例并返回 eax 寄存器中的引用。接下来,引用存储在 dword ptr [ebp-14h] 中。

下一条指令读取存储在dword ptr [ebp-14h]中的值并将该值存储在ecx寄存器中,然后用作调用的输入到构造函数 call dword ptr ds:[15398Ch] (TestApp.Program+MyClass..ctor(), mdToken: 06000003)

这解释了为什么 dso 在这种情况下两次列出引用。但是,在调试时很少需要深入了解这方面的细节。

关于c# - !DumpStackObjects 显示重复实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3814659/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com