2010-10-13 9 views
6

Ho un dump della memoria che sto usando per risolvere un problema del client. Questa è un'applicazione .NET (C#). Il problema con la mia applicazione è che vengono create troppe istanze di una particolare classe. Ci sono 6300 istanze di questa classe quando ci dovrebbe essere qualcosa come 20. Voglio scorrere tutte queste istanze e chiamare il campo del nome di ciascuna di queste istanze. C'è un modo semplice per farlo in WinDbg/SOS?ispeziona il campo su tutte le istanze nel dump della memoria

So che posso usare! Dumpheap tipo {} typename per trovare tutte le istanze di quella classe, ma non sono sicuro di come io li posso espandere e visualizzare il campo Sono interessato a.

risposta

14

Puoi farlo con il comando .foreach all'interno di Windbg.

Ecco un semplice esempio

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; 
     } 
    } 
} 

Il !dumpheap ha una breve opzione, che sarebbe solo restituire l'indirizzo oggetto. Nel caso io sono il debug MT per Program è 00293858

!dumpheap -mt 00293858 -short 

Ecco un codice per scaricare tutti gli oggetti .foreach ($obj {!dumpheap -mt 00293858 -short}) {!do $obj} utilizzando il costrutto foreach. Il $ obj verrebbe assegnato con l'indirizzo dell'oggetto. Ed ecco l'output di esempio dal ciclo 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 

Ora che abbiamo questo, il passo successivo è quello di ottenere il campo "test" all'interno di ogni istanza del programma e qui è il codice per farlo

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

Sto usando il comando poi all'interno del ciclo foreach. Dal risultato di cui sopra possiamo fare fuori la variabile test è in offset di 4 e questa è la ragione per l'utilizzo poi(${$obj}+0x4) Ed ecco l'output di esempio da quanto sopra foreach

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 << 

E qui è per ottenere ogni Foo istanza entro la classe Program

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

il Foo è l'offset 8 e qui è campionare l'uscita per il foreach sopra

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: - Anche qui è un post da Tess sul dumping contenuti sessione

HTH

+0

Questo è perfetto !! Grazie per la magnifica risposta. Ora sul vero problema di correggere la mia applicazione :) – Bryan

+0

Sì, ho trovato il post di Tess dopo che ho fatto la domanda. – Bryan

+0

spiegazione eccellente! Grazie per il dettaglio :) –

Problemi correlati