! DumpstackObjects عرض مثيلات مكررة؟
سؤال
لدي برنامج اختبار صغير. عندما أنظر إلى كائن المكدس للخيط الرئيسي ، فإن عرضه 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
مفيد لتحديد موقع الكائنات وفي هذه الحالة العمود المهم هو عمود الكائن ، الذي يحمل المراجع الفعلية.
على سبيل المثال ، إذا قمت بتشغيل مثالك أعلاه من مصحح الأخطاء ووضع نقطة استراحة على الإخراج الرئيسي من dso
يبدو أن هذا قبل عودة الطريقة الرئيسية مباشرة.
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[])
كما ترون كلاهما eax
و ال ecx
تحمل السجلات إشارة إلى المثيل على الرغم من حقيقة أن مصدر C# لديه فقط مرجع واحد.
إذا نظرت إلى رمز JIT المترجم لـ MAIN ، يبدو الأمر هكذا
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
يسرد المرجع مرتين في هذه الحالة. ومع ذلك ، نادراً ما تحتاج إلى الدخول في التفاصيل حول هذا الأمر عند تصحيح الأخطاء.