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.
encore ConsoleApplication2.Program + MyClass apparaît deux fois dans la sortie. Pourquoi deux fois et pourquoi pas une fois? – imak
@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. –
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