2012-03-25 50 views
1

我想在大型應用程序中調試內存泄漏。我的第一步是熟悉WinDBG。我在.NET下面的程序:.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 

我試圖查看WinDbg中的HelloWorld的變量,它應該是「HelloWorld」的內容。我遵循這些指示:

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內存分析器。 – 2012-03-25 16:56:40

+0

我同意,但WinDbg是免費的。你知道命令,我可以嘗試查看此字符串的內容? – w0051977 2012-03-25 17:10:41

回答

0

變量的Helloworld將被存儲在堆棧中。因此,使用!dso來轉儲堆棧對象。你應該可以看到Helloworld字符串

+0

我嘗試了你的建議。如何識別列表中的哪個字符串與HelloWorld相關: – w0051977 2012-03-25 17:09:32

+1

試試!sosex.mdso /t:System.String。這隻會轉儲出字符串,並會列出字符串值。 Sosex在http://www.stevestechspot.com免費。你也可以使用!sos.dso來做到這一點,但是它有點多。從堆棧轉儲的頂部開始,可能在寄存器中。由於你在HelloWorld字符串所在的棧幀中被破壞,它應該非常靠近頂部。 – 2012-03-26 00:00:23

0

!dumpheap -type WinDBG這裏不是正確的方法,如果你正在尋找一個字符串。如果您想爲此使用!dumpheap,則需要搜索String,因爲這是該類型的名稱。字符串是從稱爲WinDBGApplication的名稱空間內的方法引用的,這一點與此無關。然而,轉儲所有字符串會給你很多引用,即使是像這樣的小應用程序,因爲運行時分配了一堆字符串,所以這也不是很有用。

有問題的字符串實例被局部變量引用,因此找到它的最好方法是按照Rockstart建議的方式執行!dso。這將列出當前堆棧上的所有引用,並且由於該堆棧引用了該字符串,因此您可以在此處找到該地址。要轉儲字符串本身,請使用!do以及!dso輸出中顯示的字符串地址。

此外,請看看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將在主線程中產生並將你的邏輯推送到工作線程,因此你無法看到堆棧中的字符串。