! DumpstackObjects Отображение дублированных экземпляров?

StackOverflow https://stackoverflow.com/questions/3814659

  •  26-09-2019
  •  | 
  •  

Вопрос

У меня есть небольшая тестовая программа. Когда я смотрю в стек объекта для основного потока, его показаны 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 Compabled Code для главного, это выглядит так

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 Перечисляет ссылку дважды в этом случае. Тем не менее, вы редко должны пойти в детали об этом при отладке.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top