2010-09-28 6 views
4

J'ai un petit programme de test. Quand je regarde dans l'objet pile pour le fil principal, il montre deux fois MyClass là. Des idées pour lesquelles il y a deux objets de MyClass sur la pile?DumpStackObjects compréhension

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 TID: 0xf74 (0)
RER/REG Nom de l'objet
000000000023e9e8 00000000028f3c90 ConsoleApplication2.Program + MyClass
000000000023e9f8 00000000028f3c90 ConsoleApplication2.Program + MyClass
000000000023ea10 00000000028f3c70 System.Object [] (System.String [])
000000000023eb98 00000000028f3c70 System.Object [] (System.String [])
000000000023ed 80 00000000028f3c70 System.Object [] (System.String [])
000000000023eda8 00000000028f3c70 System.Object [] (System.String [])

Répondre

5

En fait, il montre que la seule et unique instance est référencé deux fois. Notez que les valeurs dans la colonne la plus à gauche diffèrent. Il peut s'agir de registres différents ou de parties différentes du cadre de pile qui pointent vers la même instance.

Dans mon expérience cela arrive assez souvent (surtout avec debug). !dso est utile pour localiser des objets et dans ce cas, la colonne importante est la colonne Objet, qui contient les références réelles.

E.g. si je lance votre exemple ci-dessus à partir du débogueur et placer un point d'arrêt sur la sortie principale de dso ressemble à ceci juste avant le retour de méthode principale.

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[]) 

Comme vous pouvez le voir à la fois le eax et les ecx registres contiennent une référence à l'instance en dépit du fait que la source C# a qu'une seule référence.

Si vous regardez le code compilé JIT pour principal il ressemble à ceci

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 

Notez l'instruction call 00142020. Cela crée l'instance de MyClass et renvoie la référence dans le registre eax. Après cela, la référence est stockée au dword ptr [ebp-14h].

L'instruction suivante lit la valeur stockée à dword ptr [ebp-14h] et stocke la valeur dans le registre ecx, qui est ensuite utilisée en entrée pour l'appel au constructeur call dword ptr ds:[15398Ch] (TestApp.Program+MyClass..ctor(), mdToken: 06000003).

Ceci explique pourquoi dso répertorie la référence deux fois dans ce cas. Cependant, vous avez rarement besoin d'entrer dans les détails à ce sujet lors du débogage.

+0

encore ConsoleApplication2.Program + MyClass apparaît deux fois dans la sortie. Pourquoi deux fois et pourquoi pas une fois? – imak

+0

@imak: Parce qu'il y a deux références au même objet. Notez les différentes entrées dans la colonne RSP/REG pointant vers la même instance. –

+0

Désolé si j'ai été stupide ici mais je ne le comprends pas. Qui possède les 2 références. C'est juste MyClass c = new MyClass(); ce qui selon mes compréhensions, variables c a une référence à MyClass; qui a l'autre référence? – imak