<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Kristoffer's tidbits : Windbg</title><link>http://blogs.msdn.com/kristoffer/archive/tags/Windbg/default.aspx</link><description>Tags: Windbg</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Debugging memory usage in managed code using Windbg</title><link>http://blogs.msdn.com/kristoffer/archive/2007/01/09/debugging-memory-usage-in-managed-code-using-windbg.aspx</link><pubDate>Tue, 09 Jan 2007 20:08:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1439777</guid><dc:creator>Kristoffer</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/kristoffer/comments/1439777.aspx</comments><wfw:commentRss>http://blogs.msdn.com/kristoffer/commentrss.aspx?PostID=1439777</wfw:commentRss><description>&lt;p&gt;Windbg, is there anything it can't do?&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=a362781c-3870-43be-8926-862b40aa0cd0&amp;amp;displaylang=en" mce_href="http://www.microsoft.com/downloads/details.aspx?familyid=a362781c-3870-43be-8926-862b40aa0cd0&amp;amp;displaylang=en"&gt;CLR Profiler&lt;/a&gt; is great for getting an overview of memory allocations and usage for managed applications but it doesn't work for very large applications and can't be attached after the application has been running for a while to determine why after 12 hours memory use spikes. Windbg can be an acceptable alternative when you find yourself looking at an unexpected memory spike and you're curious where all that memory is being allocated.&lt;/p&gt; &lt;p&gt;Start Windbg, attach to the process, and load the sos dll (&lt;a href="http://blogs.msdn.com/kristoffer/archive/2006/12/29/getting-started-with-windbg-and-managed-code.aspx" mce_href="http://blogs.msdn.com/kristoffer/archive/2006/12/29/getting-started-with-windbg-and-managed-code.aspx"&gt;see previous post&lt;/a&gt;).&lt;/p&gt; &lt;p&gt;We start out by getting a summary of our memory allocations with !dumpheap&lt;/p&gt;&lt;div class="WindbgOutput" style="white-space: pre;"&gt;0:004&amp;gt; !dumpheap -stat total 8952 objects Statistics:&lt;br&gt;       MT    Count    TotalSize Class Name &lt;br&gt;7b4779b8        1           12 System.Windows.Forms.OSFeature &lt;br&gt;7b475ca8        1           12 System.Windows.Forms.FormCollection &lt;br&gt;7b474f8c        1           12 System.Windows.Forms.Layout.DefaultLayout &lt;br&gt;7b4749e0        1           12 System.Windows.Forms.ClientUtils+WeakRefCollection &lt;br&gt;79128f18        1           12 System.Collections.Generic.GenericEqualityComparer`1[[System.Int16, mscorlib]] &lt;br&gt;79128b94        1           12 System.Collections.Generic.ObjectEqualityComparer`1[[System.IntPtr, mscorlib]] &lt;br&gt;79127ae4        1           12 System.Collections.Generic.ObjectEqualityComparer`1[[System.Object, mscorlib]] &lt;br&gt;79114408        1           12 System.Security.Permissions.ReflectionPermission &lt;br&gt;791142e8        1           12 System.Security.Permissions.FileDialogPermission &lt;br&gt;----------------- snip ---------------------- &lt;br&gt;790fd4ec       82         1968 System.Version &lt;br&gt;7ae76b24      208         2496 System.Drawing.KnownColor &lt;br&gt;791242ec       20         2952 System.Collections.Hashtable+bucket[] &lt;br&gt;79114bf0      181         5068 System.Security.SecurityElement &lt;br&gt;791036b0      229         5496 System.Collections.ArrayList &lt;br&gt;00155a48       50        23424      Free &lt;br&gt;79124228      306        47780 System.Object[] &lt;br&gt;790fa3e0     6662       379600 System.String &lt;br&gt;79124418        9      3156304 &lt;b&gt;System.Byte[]&lt;/b&gt; Total 8952 objects&lt;/div&gt; &lt;p&gt;We've got about 3 megs worth of System.Byte[] allocated so let's focus in on this to see why these objects exist.&lt;/p&gt;&lt;div class="WindbgOutput" style="white-space: pre;"&gt;0:004&amp;gt; !dumpheap -type &lt;b&gt;System.Byte[]&lt;/b&gt; &lt;br&gt;&amp;nbsp;Address       MT     Size &lt;br&gt;01241e5c 79124418       12      &lt;br&gt;0124aaf4 79124418       28      &lt;br&gt;0124ab48 79124418      140      &lt;br&gt;01251178 79124418      172      &lt;br&gt;0125129c 79124418       28      &lt;br&gt;01254f7c 79124418    10148      &lt;br&gt;&lt;b&gt;02246da8&lt;/b&gt; 79124418  1048592      &lt;br&gt;02346db8 79124418  1048592      &lt;br&gt;02446dc8 79124418  1048592      &lt;br&gt;total 9 objects &lt;br&gt;Statistics:       MT    Count    TotalSize Class Name &lt;br&gt;79124418        9      3156304 System.Byte[] &lt;br&gt;Total 9 objects&lt;/div&gt; &lt;p&gt;A few small Byte arrays but 3 of them are a meg each so let's find out why the first object is still alive (or if it is alive at all, a GC might not have happened to collect it yet).&lt;/p&gt;&lt;div class="WindbgOutput" style="white-space: pre;"&gt;0:004&amp;gt; !gcroot &lt;b&gt;02246da8&lt;/b&gt; &lt;br&gt;Note: Roots found on stacks may be false positives. Run "!help gcroot" for more info. &lt;br&gt;ebx:Root:012525d8(System.Windows.Forms.Application+ThreadContext)-&amp;gt; &lt;br&gt;01251d58(WindbgDemo.Form1)-&amp;gt; &lt;br&gt;01251edc(System.Collections.ArrayList)-&amp;gt; &lt;br&gt;0125c278(System.Object[])-&amp;gt; &lt;br&gt;02246da8(System.Byte[]) &lt;br&gt;Scan Thread 0 OSTHread 1194 &lt;br&gt;Scan Thread 2 OSTHread 1720&lt;/div&gt; &lt;p&gt;The application has a reference to Form1 which has a reference to an ArrayList which has a reference to my Byte array. If a GC were to happen right now this object would be kept alive.&lt;/p&gt; &lt;p&gt;Instead of checking each Byte array by address individually we can use the .foreach token.&lt;/p&gt;&lt;div class="WindbgOutput" style="white-space: pre;"&gt;0:004&amp;gt; .foreach (obj {!dumpheap -type &lt;b&gt;System.Byte[]&lt;/b&gt; -short}) {.echo obj;!gcroot obj} &lt;br&gt;01241e5c &lt;br&gt;Note: Roots found on stacks may be false positives. Run "!help gcroot" for more info. &lt;br&gt;Scan Thread 0 OSTHread 1194 &lt;br&gt;Scan Thread 2 OSTHread 1720 &lt;br&gt;DOMAIN(00149768):HANDLE(Pinned):3e13fc:Root:02241010(System.Object[])-&amp;gt; &lt;br&gt;01241e5c(System.Byte[]) &lt;br&gt;0124aaf4 &lt;br&gt;Note: Roots found on stacks may be false positives. Run "!help gcroot" for more info. &lt;br&gt;Scan Thread 0 OSTHread 1194 &lt;br&gt;Scan Thread 2 OSTHread 1720 &lt;br&gt;DOMAIN(00149768):HANDLE(Pinned):3e13fc:Root:02241010(System.Object[])-&amp;gt; &lt;br&gt;0124a1c4(System.Environment+ResourceHelper)-&amp;gt; &lt;br&gt;0124a358(System.Resources.ResourceManager)-&amp;gt; &lt;br&gt;0124a3a0(System.Collections.Hashtable)-&amp;gt; &lt;br&gt;0124a3d8(System.Collections.Hashtable+bucket[])-&amp;gt; &lt;br&gt;0124a9f8(System.Resources.RuntimeResourceSet)-&amp;gt; &lt;br&gt;0124aa5c(System.Resources.ResourceReader)-&amp;gt; &lt;br&gt;0124aaac(System.IO.BinaryReader)-&amp;gt; &lt;br&gt;0124aaf4(System.Byte[]) &lt;br&gt;0124ab48 &lt;br&gt;Note: Roots found on stacks may be false positives. Run "!help gcroot" for more info. &lt;br&gt;Scan Thread 0 OSTHread 1194 &lt;br&gt;Scan Thread 2 OSTHread 1720 &lt;br&gt;DOMAIN(00149768):HANDLE(Pinned):3e13fc:Root:02241010(System.Object[])-&amp;gt; &lt;br&gt;0124a1c4(System.Environment+ResourceHelper)-&amp;gt; &lt;br&gt;0124a358(System.Resources.ResourceManager)-&amp;gt; &lt;br&gt;0124a3a0(System.Collections.Hashtable)-&amp;gt; &lt;br&gt;0124a3d8(System.Collections.Hashtable+bucket[])-&amp;gt; &lt;br&gt;0124a9f8(System.Resources.RuntimeResourceSet)-&amp;gt; &lt;br&gt;0124aa5c(System.Resources.ResourceReader)-&amp;gt; &lt;br&gt;0124aaac(System.IO.BinaryReader)-&amp;gt; &lt;br&gt;0124ab48(System.Byte[]) &lt;br&gt;--------------- remainder of output snipped --------------&lt;/div&gt; &lt;p&gt;By using the /ps parameter to .foreach (see Windbg help file for details) you can run gcroot on every nth item to get a sample of objects.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1439777" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/kristoffer/archive/tags/Windbg/default.aspx">Windbg</category></item><item><title>Debugging lock issues in managed code using Windbg</title><link>http://blogs.msdn.com/kristoffer/archive/2007/01/05/debugging-lock-issues-in-managed-code-using-windbg.aspx</link><pubDate>Fri, 05 Jan 2007 19:35:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1417123</guid><dc:creator>Kristoffer</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/kristoffer/comments/1417123.aspx</comments><wfw:commentRss>http://blogs.msdn.com/kristoffer/commentrss.aspx?PostID=1417123</wfw:commentRss><description>&lt;p&gt;Windbg can be helpful for locking lock issues in managed code that seem to only happen on client machines when the moon is full and the stars are aligned just right. Windbg is a minimal installation and with managed code doesn't require debug symbols to still be useful.&lt;/p&gt;
&lt;p&gt;For my test scenario I have an application that hangs for 10 seconds at a time once a button is pressed so I start up windbg and break during the hang so I can inspect what's going on. First we check to see what the managed threads are currently running what:&lt;/p&gt;&lt;div class="WindbgOutput" style="white-space: pre;"&gt;0:000&amp;gt; ~*e!clrstack &lt;br&gt;OS Thread Id: 0x123c (0) &lt;br&gt;ESP       EIP      &lt;br&gt;0012eec8 7c82ed54 [GCFrame: 0012eec8]  0012ef98 7c82ed54 [HelperMethodFrame_1OBJ: 0012ef98] &lt;br&gt;System.Threading.Monitor.Enter(System.Object) &lt;br&gt;0012eff0 00cc0381 TestApp.Form1.button1_Click(System.Object, System.EventArgs) &lt;br&gt;0012f02c 7b060a6b System.Windows.Forms.Control.OnClick(System.EventArgs) &lt;br&gt;0012f03c 7b105379 System.Windows.Forms.Button.OnClick(System.EventArgs) &lt;br&gt;0012f048 7b10547f System.Windows.Forms.Button.OnMouseUp(System.Windows.Forms.MouseEventArgs) &lt;br&gt;0012f06c 7b0d02d2 System.Windows.Forms.Control.WmMouseUp(System.Windows.Forms.Message ByRef, System.Windows.Forms.MouseButtons, Int32) &lt;br&gt;0012f0b8 7b072c74 System.Windows.Forms.Control.WndProc(System.Windows.Forms.Message ByRef) &lt;br&gt;0012f0bc 7b0815a6 [InlinedCallFrame: 0012f0bc]  0012f158 7b0814c3 System.Windows.Forms.Button.WndProc(System.Windows.Forms.Message ByRef) &lt;br&gt;0012f160 7b07a72d System.Windows.Forms.Control+ControlNativeWindow.OnMessage(System.Windows.Forms.Message ByRef) &lt;br&gt;0012f164 7b07a706 System.Windows.Forms.Control+ControlNativeWindow.WndProc(System.Windows.Forms.Message ByRef) &lt;br&gt;0012f178 7b07a515 System.Windows.Forms.NativeWindow.Callback(IntPtr, Int32, IntPtr, IntPtr) &lt;br&gt;0012f324 0033216c [NDirectMethodFrameStandalone: 0012f324] System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG ByRef) &lt;br&gt;0012f334 7b084766 System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32, Int32, Int32) &lt;br&gt;0012f3d4 7b08432d System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext) &lt;br&gt;0012f440 7b08416b System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext) &lt;br&gt;0012f470 7b0c69fe System.Windows.Forms.Application.Run(System.Windows.Forms.Form) &lt;br&gt;0012f480 00cc00a8 TestApp.Program.Main() &lt;br&gt;0012f69c 79e88f63 [GCFrame: 0012f69c]  &lt;br&gt;OS Thread Id: 0x1408 (1) &lt;br&gt;Unable to walk the managed stack. The current thread is likely not a  &lt;br&gt;managed thread. You can run !threads to get a list of managed threads in &lt;br&gt;the process &lt;br&gt;OS Thread Id: 0xb30 (2) &lt;br&gt;Failed to start stack walk: 80004005 &lt;br&gt;OS Thread Id: 0x161c (3) &lt;br&gt;Unable to walk the managed stack. The current thread is likely not a  &lt;br&gt;managed thread. You can run !threads to get a list of managed threads in &lt;br&gt;the process &lt;br&gt;OS Thread Id: 0x149c (4) &lt;br&gt;ESP       EIP      &lt;br&gt;011ef82c 7c82ed54 [HelperMethodFrame: 011ef82c] System.Threading.Thread.SleepInternal(Int32) &lt;br&gt;011ef880 793d80f5 System.Threading.Thread.Sleep(Int32) &lt;br&gt;011ef884 00cc042d TestApp.Form1.ThreadProc() &lt;br&gt;011ef8b4 793d7a7b System.Threading.ThreadHelper.ThreadStart_Context(System.Object) &lt;br&gt;011ef8bc 793683dd System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) &lt;br&gt;011ef8d4 793d7b5c System.Threading.ThreadHelper.ThreadStart() &lt;br&gt;011efaf8 79e88f63 [GCFrame: 011efaf8]  &lt;br&gt;OS Thread Id: 0x7e0 (5) &lt;br&gt;Unable to walk the managed stack. The current thread is likely not a  &lt;br&gt;managed thread. You can run !threads to get a list of managed threads in &lt;br&gt;the process &lt;br&gt;OS Thread Id: 0xf94 (6) &lt;br&gt;Unable to walk the managed stack. The current thread is likely not a &lt;br&gt;managed thread. You can run !threads to get a list of managed threads in &lt;br&gt;the process &lt;br&gt;OS Thread Id: 0x5e4 (7) &lt;br&gt;Unable to walk the managed stack. The current thread is likely not a &lt;br&gt;managed thread. You can run !threads to get a list of managed threads in &lt;br&gt;the process&lt;/div&gt;So we've got two managed threads: 0 (the message pumping thread) and 4. Thread 0 is currently in a call to System.Threading.Monitor.Enter which the &lt;b&gt;lock&lt;/b&gt; statement wraps. Let's see what locks are held by the application. &lt;div class="WindbgOutput" style="white-space: pre;"&gt;0:000&amp;gt; !syncblk &lt;br&gt;Index SyncBlock MonitorHeld Recursion Owning Thread Info  SyncBlock Owner    &lt;br&gt;11 001b415c            3         1 001be180  149c   4   &lt;b&gt;012cfdfc&lt;/b&gt; TestApp.Form1 &lt;br&gt;----------------------------- &lt;br&gt;Total           11 &lt;br&gt;CCW             0 &lt;br&gt;RCW             0 &lt;br&gt;ComClassFactory 0 &lt;br&gt;Free            0&lt;/div&gt;So thread 4 (which is currently sleeping) holds a lock on the object at address 012cfdfc. Let's see what type of object this is: &lt;div class="WindbgOutput" style="white-space: pre;"&gt;0:000&amp;gt; !DumpObj -nofields &lt;b&gt;012cfdfc&lt;/b&gt; &lt;br&gt;Name: TestApp.Form1 &lt;br&gt;MethodTable: &lt;b&gt;008f5ac4&lt;/b&gt; &lt;br&gt;EEClass: 008f165c &lt;br&gt;Size: 332(0x14c) bytes &lt;br&gt; (C:\Testing\WindowsApplication17\WindowsApplication17\bin\Debug\WindowsApplication17.exe)&lt;/div&gt;Thread 4 has a lock on the Form. Looking at the stack objects for thread 0 we can see the Form object right before a synchronization context. &lt;div class="WindbgOutput" style="white-space: pre;"&gt;0:000&amp;gt; !dso &lt;br&gt;OS Thread Id: 0x123c (0) &lt;br&gt;ESP/REG  Object   Name &lt;br&gt;0012edd0 012d05f4 System.Windows.Forms.WindowsFormsSynchronizationContext &lt;br&gt;0012ef00 &lt;b&gt;012cfdfc&lt;/b&gt; TestApp.Form1 &lt;br&gt;0012ef54 012f9f1c System.Threading.ThreadStart &lt;br&gt;0012ef58 012f9f3c System.Threading.Thread &lt;br&gt;0012ef64 012f9f1c System.Threading.ThreadStart &lt;br&gt;0012ef6c 012f9f3c System.Threading.Thread &lt;br&gt;0012efac 012cff60 Microsoft.Win32.SafeHandles.SafeWaitHandle &lt;br&gt;0012efd4 012cfdfc TestApp.Form1 &lt;br&gt;0012eff0 012cfdfc TestApp.Form1 &lt;br&gt;0012eff4 012f9f3c System.Threading.Thread &lt;br&gt;0012eff8 012cfdfc TestApp.Form1 &lt;br&gt;0012effc 012ea688 System.Windows.Forms.Button &lt;br&gt;-------------- snip -----------------------&lt;br&gt; 0012f46c 012ec1e0 System.Windows.Forms.ApplicationContext &lt;br&gt;0012f474 012cfdfc TestApp.Form1&lt;/div&gt;We can confirm this by looking at the IL code for TestApp.Form1.button1_Click. &lt;div class="WindbgOutput" style="white-space: pre;"&gt;0:000&amp;gt; !dumpmt -md &lt;b&gt;008f5ac4&lt;/b&gt; &lt;br&gt;EEClass: 008f165c &lt;br&gt;Module: 008f2d5c &lt;br&gt;Name: TestApp.Form1 &lt;br&gt;mdToken: 02000003 &lt;br&gt; (C:\Testing\WindowsApplication17\WindowsApplication17\bin\Debug\WindowsApplication17.exe)&lt;br&gt;BaseSize: 0x14c &lt;br&gt;ComponentSize: 0x0 &lt;br&gt;Number of IFaces in IFaceMap: 15 &lt;br&gt;Slots in VTable: 376 &lt;br&gt;-------------------------------------- &lt;br&gt;MethodDesc Table &lt;br&gt;&amp;nbsp; &amp;nbsp;Entry MethodDesc      JIT Name &lt;br&gt;7b05c298   7b4a5518   PreJIT System.Windows.Forms.Form.ToString() &lt;br&gt;793539c0   7913bd50   PreJIT System.Object.Equals(System.Object) &lt;br&gt;793539b0   7913bd68   PreJIT System.Object.GetHashCode() &lt;br&gt;7a4a6510   7a75bf58   PreJIT System.ComponentModel.Component.Finalize() &lt;br&gt;79361e50   7913dbd8   PreJIT System.MarshalByRefObject.GetLifetimeService() &lt;br&gt;7b0662a4   7b4a5530   PreJIT System.Windows.Forms.Form.OnResizeEnd(System.EventArgs) &lt;br&gt;------------------ snip -----------------&lt;br&gt;008f61d4   008f5a68      JIT TestApp.Form1.InitializeComponent() &lt;br&gt;008f61b0   008f5a70      JIT TestApp.Form1..ctor() &lt;br&gt;008f6cfc   008f5a78      JIT TestApp.Form1.ThreadProc() &lt;br&gt;008f6a54   &lt;b&gt;008f5a80&lt;/b&gt;      JIT TestApp.Form1.button1_Click(System.Object, System.EventArgs) &lt;br&gt;0:000&amp;gt; !dumpil &lt;b&gt;008f5a80&lt;/b&gt; &lt;br&gt;ilAddr = 00402274 &lt;br&gt;IL_0000: nop &lt;br&gt;IL_0001: ldarg.0 &lt;br&gt;IL_0002: ldftn TestApp.Form1::ThreadProc&lt;br&gt;IL_0008: newobj System.Threading.ThreadStart::.ctor &lt;br&gt;IL_000d: newobj System.Threading.Thread::.ctor &lt;br&gt;IL_0012: stloc.0 &lt;br&gt;IL_0013: ldloc.0 &lt;br&gt;IL_0014: callvirt System.Threading.Thread::Start &lt;br&gt;IL_0019: nop &lt;br&gt;IL_001a: ldarg.0 &lt;br&gt;IL_001b: ldfld TestApp.Form1::threadStarted&lt;br&gt;IL_0020: callvirt System.Threading.WaitHandle::WaitOne &lt;br&gt;IL_0025: pop &lt;br&gt;&lt;b&gt;IL_0026: ldarg.0 &lt;br&gt;IL_0027: dup &lt;br&gt;IL_0028: stloc.1 &lt;br&gt;IL_0029: call System.Threading.Monitor::Enter&lt;/b&gt; &lt;br&gt;IL_002e: nop &lt;br&gt;.try&lt;br&gt;{&lt;br&gt;&amp;nbsp; IL_002f: nop &lt;br&gt;&amp;nbsp; IL_0030: nop &lt;br&gt;&amp;nbsp; IL_0031: leave.s IL_003b&lt;br&gt;} // end .try&lt;br&gt;.finally&lt;br&gt;{&lt;br&gt;&amp;nbsp; IL_0033: ldloc.1 &lt;br&gt;&amp;nbsp; IL_0034: call System.Threading.Monitor::Exit &lt;br&gt;&amp;nbsp; IL_0039: nop &lt;br&gt;&amp;nbsp; IL_003a: endfinally &lt;br&gt;} // end .finally&lt;br&gt;IL_003b: nop &lt;br&gt;IL_003c: ldloc.0 &lt;br&gt;IL_003d: callvirt System.Threading.Thread::Join &lt;br&gt;IL_0042: nop &lt;br&gt;IL_0043: ret &lt;br&gt;&lt;/div&gt;Sure enough Form1 is passing itself to System.Threading.Monitor.Enter.&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1417123" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/kristoffer/archive/tags/Windbg/default.aspx">Windbg</category></item><item><title>Debugging exceptions in managed code using Windbg</title><link>http://blogs.msdn.com/kristoffer/archive/2007/01/03/debugging-exceptions-in-managed-code-using-windbg.aspx</link><pubDate>Wed, 03 Jan 2007 19:04:27 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1405113</guid><dc:creator>Kristoffer</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/kristoffer/comments/1405113.aspx</comments><wfw:commentRss>http://blogs.msdn.com/kristoffer/commentrss.aspx?PostID=1405113</wfw:commentRss><description>&lt;p&gt;By default Windbg will break for access violations (or null reference exceptions as they're called in managed code). To get Windbg to break for managed exceptions use the sxe command.&lt;/p&gt;&lt;div class="WindbgOutput" style="white-space: pre"&gt;0:004&amp;gt; sxe clr&lt;br&gt;0:004&amp;gt; g&lt;/div&gt; &lt;p&gt;A little while later our program generates a CLR exception and pops into the debugger.&lt;/p&gt;&lt;div class="WindbgOutput" style="white-space: pre"&gt;(17c.1194): CLR exception - code e0434f4d (first chance)&lt;br&gt;First chance exceptions are reported before any exception handling.&lt;br&gt;This exception may be expected and handled.&lt;br&gt;eax=0012eea0 ebx=0014d578 ecx=00000000 edx=00000025 esi=0012ef2c edi=e0434f4d&lt;br&gt;eip=77e55e02 esp=0012ee9c ebp=0012eef0 iopl=0         nv up ei pl nz na po nc&lt;br&gt;cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202&lt;br&gt;KERNEL32!RaiseException+0x53:&lt;br&gt;77e55e02 5e              pop     esi&lt;/div&gt; &lt;p&gt;This is a first chance exception so this may be expected and handled, as the message helpfully reminds you. Let's find out what caused this exception.&lt;/p&gt;&lt;div class="WindbgOutput" style="white-space: pre"&gt;0:000&amp;gt; !PrintException&lt;br&gt;Exception object: 01289fb0&lt;br&gt;Exception type: System.ArgumentException&lt;br&gt;Message: Value does not fall within the expected range.&lt;br&gt;InnerException: &amp;lt;none&amp;gt;&lt;none&gt;&lt;br&gt;StackTrace (generated):&lt;br&gt;&amp;lt;none&amp;gt;&lt;br&gt;StackTraceString: &amp;lt;none&amp;gt;&lt;br&gt;HResult: 80070057&lt;/div&gt; &lt;p&gt;We can also have a look at the managed stack trace to see where this exception happened.&lt;/p&gt;&lt;div class="WindbgOutput" style="white-space: pre"&gt;0:000&amp;gt; !CLRStack&lt;br&gt;OS Thread Id: 0x1194 (0)&lt;br&gt;ESP       EIP      &lt;br&gt;0012ef78 77e55e02 [HelperMethodFrame: 0012ef78]&lt;br&gt;0012f01c 00cc0795 WindbgDemo.Form1.CauseOtherException()&lt;br&gt;0012f024 00cc075d WindbgDemo.Form1.btnOtherException_Click(System.Object, System.EventArgs)&lt;br&gt;0012f02c 7b060a6b System.Windows.Forms.Control.OnClick(System.EventArgs)&lt;br&gt;0012f03c 7b105379 System.Windows.Forms.Button.OnClick(System.EventArgs) &lt;br&gt;0012f048 7b10547f System.Windows.Forms.Button.OnMouseUp(System.Windows.Forms.MouseEventArgs)&lt;br&gt;0012f06c 7b0d02d2 System.Windows.Forms.Control.WmMouseUp(System.Windows.Forms.Message ByRef, System.Windows.Forms.MouseButtons, Int32)&lt;br&gt;0012f0b8 7b072c74 System.Windows.Forms.Control.WndProc(System.Windows.Forms.Message ByRef)&lt;br&gt;0012f0bc 7b0815a6 [InlinedCallFrame: 0012f0bc] &lt;br&gt;0012f158 7b0814c3 System.Windows.Forms.Button.WndProc(System.Windows.Forms.Message ByRef)&lt;br&gt;0012f160 7b07a72d System.Windows.Forms.Control+ControlNativeWindow.OnMessage(System.Windows.Forms.Message ByRef)&lt;br&gt;0012f164 7b07a706 System.Windows.Forms.Control+ControlNativeWindow.WndProc(System.Windows.Forms.Message ByRef)&lt;br&gt;0012f178 7b07a515 System.Windows.Forms.NativeWindow.Callback(IntPtr, Int32, IntPtr, IntPtr)&lt;br&gt;0012f324 0033216c [NDirectMethodFrameStandalone: 0012f324] System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG ByRef)&lt;br&gt;0012f334 7b084766 System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32, Int32, Int32)&lt;br&gt;0012f3d4 7b08432d System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)&lt;br&gt;0012f440 7b08416b System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext)&lt;br&gt;0012f470 7b0c69fe System.Windows.Forms.Application.Run(System.Windows.Forms.Form)&lt;br&gt;0012f480 00cc0097 WindbgDemo.Program.Main()&lt;br&gt;0012f69c 79e88f63 [GCFrame: 0012f69c]&lt;/div&gt; &lt;p&gt;If we want to get a feel for what sorts of exceptions are generated by our program but not necessarily inspect each one we can tell Windbg to stop on exceptions, print out some information about the exception, and then continue running all without user intervention.&lt;/p&gt;&lt;div class="WindbgOutput" style="white-space: pre"&gt;0:000&amp;gt; sxe -c "!pe;!clrstack;gc" clr&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1405113" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/kristoffer/archive/tags/Windbg/default.aspx">Windbg</category></item><item><title>Setting a breakpoint in managed code using Windbg</title><link>http://blogs.msdn.com/kristoffer/archive/2007/01/02/setting-a-breakpoint-in-managed-code-using-windbg.aspx</link><pubDate>Tue, 02 Jan 2007 19:49:06 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1399686</guid><dc:creator>Kristoffer</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/kristoffer/comments/1399686.aspx</comments><wfw:commentRss>http://blogs.msdn.com/kristoffer/commentrss.aspx?PostID=1399686</wfw:commentRss><description>&lt;p&gt;One of the great features of managed code is getting call stacks and proper class and member function names without debug symbols. We can examine the methods of a class and set breakpoints based on name.&lt;/p&gt; &lt;p&gt;To see the methods on an object in Windbg we first need to find its method table. We can do this with the !name2ee command which will look up information about a class.&lt;/p&gt;&lt;div class="WindbgOutput" style="white-space: pre"&gt;0:004&amp;gt; !Name2EE *!WindbgDemo.Form1&lt;br&gt;Module: 790c2000 (mscorlib.dll)&lt;br&gt;--------------------------------------&lt;br&gt;Module: 00912380 sortkey.nlp)&lt;br&gt;--------------------------------------&lt;br&gt;Module: 00912010 (sorttbls.nlp)&lt;br&gt;--------------------------------------&lt;br&gt;Module: 008f2d5c (WindbgDemo.exe)&lt;br&gt;Token: 0x02000004&lt;br&gt;MethodTable: &lt;strong&gt;008f5b5c&lt;/strong&gt;&lt;br&gt;EEClass: 008f15dc&lt;br&gt;Name: WindbgDemo.Form1&lt;br&gt;--------------------------------------&lt;br&gt;Module: 7b442000 (System.Windows.Forms.dll)&lt;br&gt;--------------------------------------&lt;br&gt;Module: 7a714000 (System.dll)&lt;br&gt;--------------------------------------&lt;br&gt;Module: 7ae72000 (System.Drawing.dll)&lt;/div&gt; &lt;p&gt;With the method table address we can examine all the methods defined on the object.&lt;/p&gt;&lt;div class="WindbgOutput" style="white-space: pre"&gt;0:004&amp;gt; !DumpMT -MD &lt;strong&gt;008f5b5c&lt;/strong&gt;&lt;br&gt;EEClass: 008f15dc&lt;br&gt;Module: 008f2d5c&lt;br&gt;Name: WindbgDemo.Form1&lt;br&gt;mdToken: 02000004  (C:\Testing\WindbgDemo\WindbgDemo\bin\Release\WindbgDemo.exe)&lt;br&gt;BaseSize: 0x16c&lt;br&gt;ComponentSize: 0x0&lt;br&gt;Number of IFaces in IFaceMap: 15&lt;br&gt;Slots in VTable: 383&lt;br&gt;--------------------------------------&lt;br&gt;MethodDesc Table&lt;br&gt;   Entry MethodDesc      JIT Name&lt;br&gt;7b05c298   7b4a5518   PreJIT System.Windows.Forms.Form.ToString()&lt;br&gt;793539c0   7913bd50   PreJIT System.Object.Equals(System.Object)&lt;br&gt;793539b0   7913bd68   PreJIT System.Object.GetHashCode()&lt;br&gt;7a4a6510   7a75bf58   PreJIT System.ComponentModel.Component.Finalize()&lt;br&gt;79361e50   7913dbd8   PreJIT System.MarshalByRefObject.GetLifetimeService()&lt;br&gt;79360770   7913dbe0   PreJIT System.MarshalByRefObject.InitializeLifetimeService()&lt;br&gt;--------------- snip ----------------&lt;br&gt;7b06621c   7b4a5528   PreJIT System.Windows.Forms.Form.OnResizeBegin(System.EventArgs)&lt;br&gt;7b0662a4   7b4a5530   PreJIT System.Windows.Forms.Form.OnResizeEnd(System.EventArgs)&lt;br&gt;008f62a0   008f5ac8      JIT WindbgDemo.Form1.InitializeComponent()&lt;br&gt;008f627c   008f5ad0      JIT WindbgDemo.Form1..ctor()&lt;br&gt;008f62bc   008f5ad8     NONE WindbgDemo.Form1.btnLockBlock_Click(System.Object, System.EventArgs)&lt;br&gt;008f6249   008f5ae0     NONE WindbgDemo.Form1.LockBlock()&lt;br&gt;008f62d0   008f5ae8     NONE WindbgDemo.Form1.btnException_Click(System.Object, System.EventArgs)&lt;br&gt;008f6251   008f5af0     NONE WindbgDemo.Form1.CauseException()&lt;br&gt;008f630c   008f5af8     NONE WindbgDemo.Form1.btnOtherException_Click(System.Object, System.EventArgs)&lt;br&gt;008f6259   008f5b00     NONE WindbgDemo.Form1.CauseOtherException()&lt;br&gt;008f62e4   008f5b08     NONE WindbgDemo.Form1.btnMemoryGrowth_Click(System.Object, System.EventArgs)&lt;br&gt;008f62f8   &lt;strong&gt;008f5b10&lt;/strong&gt;     NONE WindbgDemo.Form1.btnBreakpoint_Click(System.Object, System.EventArgs)&lt;br&gt;008f6265   008f5b18     NONE WindbgDemo.Form1.Foo()&lt;/div&gt; &lt;p&gt;For the curious we can see whether the function is ngen'ed code or if it has been JITted yet. PreJIT means ngen code, JIT and NONE is whether the function has been JITted or not. From here we can set a breakpoint.&lt;/p&gt;&lt;div class="WindbgOutput" style="white-space: pre"&gt;0:004&amp;gt; !bpmd -md &lt;b&gt;008f5b10&lt;/b&gt; &lt;br&gt;MethodDesc = 008f5b10&lt;br&gt;Adding pending breakpoints...&lt;/div&gt; &lt;p&gt;It's a pending breakpoint because this code has not been jitted yet and thus has no place to put the debug breakpoint. You can also set breakpoints directly by name using !bpmd.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1399686" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/kristoffer/archive/tags/Windbg/default.aspx">Windbg</category></item><item><title>Getting started with Windbg and managed code</title><link>http://blogs.msdn.com/kristoffer/archive/2006/12/29/getting-started-with-windbg-and-managed-code.aspx</link><pubDate>Sat, 30 Dec 2006 00:51:10 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1381372</guid><dc:creator>Kristoffer</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/kristoffer/comments/1381372.aspx</comments><wfw:commentRss>http://blogs.msdn.com/kristoffer/commentrss.aspx?PostID=1381372</wfw:commentRss><description>&lt;p&gt;&lt;a href="http://www.microsoft.com/whdc/devtools/debugging/default.mspx"&gt;Windbg&lt;/a&gt; (or wind bag as my friend calls it) is my one stop shop for almost everything debugging related. It's great for finding issues that only happen on a client machine and you don't want a full blown Visual Studio installation mucking up your repro.&lt;/p&gt; &lt;p&gt;With the &lt;strong&gt;sos&lt;/strong&gt; extension Windbg becomes useful at debugging managed code as well. To get started with Windbg and sos fire up Windbg and attach to a managed process. I'm using .Net 2.0 for my development so I need to load the sos dll from the Framework directory (for 1.1 .Net use .load clr10\sos.dll instead) . I can do this with the .loadby command: &lt;div class="WindbgOutput"&gt;0:000&amp;gt; .loadby sos mscorwks&lt;/div&gt; &lt;p&gt;This tells Windbg to load the debugger extension sos.dll from the same directory that the current process has mscorwks.dll loaded from.&lt;br&gt;Next we hit Debug | Go (or F5) and the process is now happily running away. &lt;/p&gt; &lt;p&gt;Once the problem occurs go back to Windbg and press Debug | Break and we can now examine the process state in safety. If at any point you need help with the sos commands, &lt;b&gt;!help&lt;/b&gt; will get you going.&lt;/p&gt; &lt;p&gt;Coming up next week: using Windbg to debug exceptions, deadlocks, and memory problems in managed code.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1381372" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/kristoffer/archive/tags/Windbg/default.aspx">Windbg</category></item></channel></rss>