2010-10-13 7 views
6

J'ai un vidage de la mémoire que j'utilise pour résoudre un problème client. Ceci est une application .NET (C#). Le problème avec mon application est que trop d'instances d'une classe particulière sont en cours de création. Il y a 6300 instances de cette classe quand il devrait y avoir quelque chose comme 20. Je veux parcourir toutes ces instances et appeler le champ de nom de chacune de ces instances. Y at-il un moyen facile de le faire dans WinDbg/SOS?inspecter le champ sur toutes les instances dans le vidage de la mémoire

Je sais que je peux utiliser! Dumpheap {typename} -type pour trouver toutes les instances de cette classe, mais je ne sais pas comment

Répondre

14

je peux les développer tout et voir le terrain, je suis intéressé par. Vous pouvez le faire avec la commande .foreach dans Windbg.

Voici un exemple simple

using System; 
using System.Collections.Generic; 
using System.Linq; 
namespace Test 
{ 
    class Program 
    { 
     static List<Program> list = new List<Program>(); 
     int i; 
     string test; 
     Foo f; 
     static void Main(string[] args) 
     { 
      for (int i = 0; i < 10; i++) 
      { 
       list.Add(new Program() { i = i, test = "Test" + i.ToString(), f = new Foo(i) }); 
      } 
      Console.Read(); 
     } 
    } 
    class Foo 
    { 
     int j; 
     public Foo(int i) 
     { 
      j = i; 
     } 
    } 
} 

Le !dumpheap a une option courte qui serait juste renvoyer l'adresse de l'objet. Dans le cas je suis débogage MT pour Program est 00293858

!dumpheap -mt 00293858 -short 

Voici un code pour vider tous les objets .foreach ($obj {!dumpheap -mt 00293858 -short}) {!do $obj} à l'aide de la construction foreach. Le $ obj serait assigné avec l'adresse de l'objet. Et voici l'exemple de sortie de la boucle foreach

Name:  Test.Program 
MethodTable: 00293858 
EEClass:  00291440 
Size:  20(0x14) bytes 
File:  c:\users\nsrinivasan\documents\visual studio 2010\Projects\Test\Test\bin\Debug\Test.exe 
Fields: 
     MT Field Offset     Type VT  Attr Value Name 
5c2e2978 4000002  c   System.Int32 1 instance  3 i 
5c2df9ac 4000003  4  System.String 0 instance 0217c144 test 
00293bfc 4000004  8    Test.Foo 0 instance 0217c15c f 
002938b4 4000001  4 ...t.Program, Test]] 0 static 0217b97c list 
Name:  Test.Program 
MethodTable: 00293858 
EEClass:  00291440 
Size:  20(0x14) bytes 
File:  c:\users\nsrinivasan\documents\visual studio 2010\Projects\Test\Test\bin\Debug\Test.exe 
Fields: 
     MT Field Offset     Type VT  Attr Value Name 
5c2e2978 4000002  c   System.Int32 1 instance  4 i 
5c2df9ac 4000003  4  System.String 0 instance 0217c18c test 
00293bfc 4000004  8    Test.Foo 0 instance 0217c1a4 f 
002938b4 4000001  4 ...t.Program, Test]] 0 static 0217b97c list 

Maintenant que nous avons cela, l'étape suivante est d'obtenir le champ « test » dans chaque instance du programme et le code ici pour le faire

.foreach ($obj {!dumpheap -mt 00293858 -short}) {!do poi(${$obj}+0x4)} 

J'utilise la commande poi dans la boucle foreach. A partir du résultat ci-dessus, nous pouvons faire à la variable test est dans le 4 offset et qui est la raison d'utiliser poi(${$obj}+0x4) Et voici la sortie de l'échantillon de l'foreach ci-dessus

0:004> .foreach ($obj {!dumpheap -mt 00293858  -short}) {!do poi(${$obj}+0x4)} 
Name:  System.String 
MethodTable: 5c2df9ac 
EEClass:  5c018bb0 
Size:  24(0x18) bytes 
File:  C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll 
String:  Test0 
Fields: 
     MT Field Offset     Type VT  Attr Value Name 
5c2e2978 40000ed  4   System.Int32 1 instance  5 m_stringLength 
5c2e1dc8 40000ee  8   System.Char 1 instance  54 m_firstChar 
5c2df9ac 40000ef  8  System.String 0 shared static Empty 
    >> Domain:Value 002f76c0:02171228 << 
Name:  System.String 
MethodTable: 5c2df9ac 
EEClass:  5c018bb0 
Size:  24(0x18) bytes 
File:  C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll 
String:  Test1 
Fields: 
     MT Field Offset     Type VT  Attr Value Name 
5c2e2978 40000ed  4   System.Int32 1 instance  5 m_stringLength 
5c2e1dc8 40000ee  8   System.Char 1 instance  54 m_firstChar 
5c2df9ac 40000ef  8  System.String 0 shared static Empty 
    >> Domain:Value 002f76c0:02171228 << 

Et est ici pour obtenir chaque Foo instance dans la classe Program

.foreach ($obj {!dumpheap -mt 00293858 -short}) {!do poi(${$obj}+0x8)} 

le Foo est dans le 8ème offset et voici échantillonner la sortie pour le foreach ci-dessus

Name:  Test.Foo 
MethodTable: 00293bfc 
EEClass:  0029194c 
Size:  12(0xc) bytes 
File:  c:\users\nsrinivasan\documents\visual studio 2010\Projects\Test\Test\bin\Debug\Test.exe 
Fields: 
     MT Field Offset     Type VT  Attr Value Name 
5c2e2978 4000005  4   System.Int32 1 instance  0 j 
Name:  Test.Foo 
MethodTable: 00293bfc 
EEClass:  0029194c 
Size:  12(0xc) bytes 
File:  c:\users\nsrinivasan\documents\visual studio 2010\Projects\Test\Test\bin\Debug\Test.exe 
Fields: 
     MT Field Offset     Type VT  Attr Value Name 
5c2e2978 4000005  4   System.Int32 1 instance  1 j 

EDIT: - Aussi voici une post de Tess sur le dumping contenu de la session

HTH

+0

C'est parfait !! Merci pour la bonne réponse. Maintenant, sur le vrai problème de la réparation de mon application :) – Bryan

+0

Ouais, j'ai trouvé le post de Tess après avoir posé la question. – Bryan

+0

excellente explication! Merci pour le détail :) –

Questions connexes