2012-03-25 19 views
1

大きなアプリケーションでメモリリークをデバッグしようとしています。私の第一歩はWinDBGに慣れ親しむことです。私は、.NETで次のプログラムを持っている:私は「HelloWorldの」あるべきWinDbgのでHelloWorldの変数の内容を表示しようとしています.NET - WinDBG - 文字列の内容

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
    Try 
     Dim HelloWorld As String = "HelloWorld" 
     Dim testInt As Integer 
     Me.Show() 
     For testInt = 0 To 1000000 
      TextBox1.Text = testInt 'There is a textbox on the form 
      Application.DoEvents() 'So textbox updates on the fly 
     Next 

    Catch ex As Exception 

    End Try 
End Sub 

。私はこれらの指示に従いました:

1)実行可能にWinDBGを添付し、デバッガを起動します。

2)ループが終了する前に

3)loadby SOS CLR

4)(すぐブレーク)〜0

5)!clrstack

6)!dumpheap型WinDBGの(プロジェクトはWinDBGApplicationと呼ばれる)

出力はこれです:

Statistics: 
     MT Count TotalSize Class Name 
00186f88  1   12  WinDBGTest.My.MyProject+ThreadSafeObjectProvider`1[[WinDBGTest.My.MyProject+MyWebServices, WinDBGTest]] 
00186e80  1   12 WinDBGTest.My.MyProject+ThreadSafeObjectProvider`1[[WinDBGTest.My.MyProject+MyForms, WinDBGTest]] 
00186e2c  1   12 WinDBGTest.My.MyProject+MyForms 
00186d3c  1   12 WinDBGTest.My.MyProject+ThreadSafeObjectProvider`1[[Microsoft.VisualBasic.ApplicationServices.User, Microsoft.VisualBasic]] 
00186cec  1   12 WinDBGTest.My.MyProject+ThreadSafeObjectProvider`1[[WinDBGTest.My.MyComputer, WinDBGTest]] 
00186be8  1   12 WinDBGTest.My.MyProject+ThreadSafeObjectProvider`1[[WinDBGTest.My.MyApplication, WinDBGTest]] 
00184bf4  1   104 WinDBGTest.My.MyApplication 
00187308  1   328 WinDBGTest.Form1 
Total 8 objects 

HelloWorldという文字列の証拠はなく、低レベルのデバッグに関する限られた知識に基づいているはずです。私は間違って何をしていますか?

私はRockstartによって提案されたものをしようと、この出力を取得しています

OS Thread Id: 0x7a0 (0) 
ESP/REG Object Name 
0039E5EC 0234db94 System.Windows.Forms.Control+ControlNativeWindow 
0039E63C 0234dadc System.Windows.Forms.TextBox 
0039E658 0234dadc System.Windows.Forms.TextBox 
0039E668 0234dadc System.Windows.Forms.TextBox 
0039E680 0234db94 System.Windows.Forms.Control+ControlNativeWindow 
0039E698 0234db94 System.Windows.Forms.Control+ControlNativeWindow 
0039E6A8 0234db94 System.Windows.Forms.Control+ControlNativeWindow 
0039E7FC 0234dadc System.Windows.Forms.TextBox 
0039E864 02604b10 System.Windows.Forms.Control+MultithreadSafeCallScope 
0039E868 02604b68 System.String 26309 
0039E878 026049a8 System.String 26310 
0039E87C 0234dadc System.Windows.Forms.TextBox 
0039E880 026049a8 System.String 26310 
0039E884 0234db94 System.Windows.Forms.Control+ControlNativeWindow 
0039E890 0234db94 System.Windows.Forms.Control+ControlNativeWindow 
0039E8A0 026049a8 System.String 26310 
0039E8AC 0234dadc System.Windows.Forms.TextBox 
0039E8B4 0234db84 System.Windows.Forms.PropertyStore 
0039E8C8 0234dadc System.Windows.Forms.TextBox 
0039E8CC 026049a8 System.String 26310 
0039E8DC 026049a8 System.String 26310 
0039E8E0 0234dadc System.Windows.Forms.TextBox 
0039E8EC 0234dadc System.Windows.Forms.TextBox 
0039E8F0 0234dadc System.Windows.Forms.TextBox 
0039E904 0234d4e4 WinDBGTest.Form1 
0039E940 0234d4e4 WinDBGTest.Form1 
0039E944 0234e4c0 System.EventHandler 
0039E970 0234a1c4 System.EventArgs 
0039E978 0234d4e4 WinDBGTest.Form1 
0039E9DC 0234d4e4 WinDBGTest.Form1 
0039EA00 0234d4e4 WinDBGTest.Form1 
0039EAE0 0234d984 System.Windows.Forms.Control+ControlNativeWindow 
0039ED28 0234d4e4 WinDBGTest.Form1 
0039ED34 0234d4e4 WinDBGTest.Form1 
0039ED3C 0234d4e4 WinDBGTest.Form1 
0039ED44 0234d4e4 WinDBGTest.Form1 
0039ED4C 0234d4e4 WinDBGTest.Form1 
0039EDCC 0234d4e4 WinDBGTest.Form1 
0039EE18 023491c8 System.Windows.Forms.Application+ThreadContext 
0039EE58 023490c8 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase+WinFormsAppContext 
0039EE8C 02348f54 WinDBGTest.My.MyApplication 
0039EEA8 02348f54 WinDBGTest.My.MyApplication 
0039EEB8 02348f54 WinDBGTest.My.MyApplication 
0039F1D8 02348640 System.Object[] (System.String[]) 
+0

これは完全に不可能ではありませんが、windbgはリークのトラブルシューティングにはかなり泥だらけのツールです。データの山に溺れないようにするのに役立つのはほんのわずかですが、ノイズと信号の比は非常に貧弱です。代わりに.NETメモリプロファイラを使用してください。 –

+0

私は同意しますが、WinDbgは無料です。この文字列の内容を見ることができるコマンドを知っていますか? – w0051977

答えて

0

変数のHelloWorldがスタックに格納されていたであろう。したがって、!dsoを使用してスタックオブジェクトをダンプします。あなたが文字列を探しているなら、Helloworldの文字列

+0

私はあなたの提案を試みました。リストからどの文字列がHelloWorldに関連しているかを特定する方法を教えてください。 – w0051977

+1

試してください!sosex.mdso /t:System.String。これにより、文字列だけがダンプされ、文字列値もリストされます。 Sosexはhttp://www.stevestechspot.comで無料です。 !sos.dsoでこれを行うこともできますが、もう少し作業が必要です。おそらくレジスタ内のスタックダンプの先頭から開始します。 HelloWorld文字列が存在するスタックフレームが壊れているので、上部に非常に近いはずです。 –

0

1210が正しいアプローチではないはずです。これに!dumpheapを使用する場合は、そのタイプの名前であるStringを検索する必要があります。 WinDBGApplicationという名前空間内のメソッドから文字列が参照されるという事実は、ここでは関係ありません。しかし、すべての文字列をダンプすると、このような小さなアプリケーションであっても、ランタイムがたくさんの文字列を割り当てるため、多くの参照が得られます。

問題の文字列インスタンスはローカル変数によって参照されるため、ロックスタートで提案されているように!dsoを実行するのが最もよい方法です。これにより、現在のスタック上のすべての参照がリストされ、このスタックによって文字列が参照されるため、ここでそのアドレスを見つけることができます。文字列自体をダンプするには、!dsoの出力に表示されている文字列のアドレスを使用して!doを使用します。

また、this questionをご覧ください。

0

はどのようにあなたはループが終了する前に壊れることを確保している「2)ループが終了する前に()直後にブレーク」? windbgでブレークポイントを保持していますか?この分割が適切な場所で行われないと、スタック内の文字列を取得できないことがあります。

デスクトップでも同様のプログラムを試しましたが、文字列が表示されました。ここに私のサンプルプログラムがあります。

class Program 
{ 
    static void Main(string[] args) 
    { 
     var testclass = new testClass(); 
     testclass.Load(); 
    } 


} 

public class testClass 
{ 
    public void Load() 
    { 
     var HelloWorld = "Hello World!!"; 
     string temp = string.Empty; 
     for (int i = 0; i < 1000; i++) 
     { 
      temp = i.ToString(); 

      if (i == 400) 
      { 
       Console.ReadKey(); 
      } 
     } 
    } 
} 

}

制御がConsole.ReadKeyを()に達したとき、私はデバッガを添付して!のDSOを走りました。 結果は次のとおりです。

enter image description here

一つ別のアプローチは、あなたが "Me.Showを()" を削除して、もう一度同じことを試すことができます。私は恐れている、Me.Showはメインスレッドで生成され、あなたのロジックをワーカースレッドにプッシュするので、スタック内の文字列を見ることができません。

関連する問題