{"id":744,"date":"2009-12-03T00:00:00","date_gmt":"2009-12-03T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/a-look-at-exceptions-in-net-applications\/"},"modified":"2021-05-17T18:36:37","modified_gmt":"2021-05-17T18:36:37","slug":"a-look-at-exceptions-in-net-applications","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/a-look-at-exceptions-in-net-applications\/","title":{"rendered":"A Look at Exceptions in .NET Applications"},"content":{"rendered":"<div id=\"pretty\">\n<p class=\"START\">In this article I am going to continue on from my last article, <a href=\"https:\/\/www.red-gate.com\/simple-talk\/dotnet\/net-framework\/net-debugging-dont-give-me-none-of-your-vs\/\">Don&#8217;t Give me none of your VS<\/a>, by looking at how to debug in the mysterious world where the debugging tools for Windows hold sway, and <b>sos.dll<\/b> turns CLR internals into a veritable fountain of knowledge. Specifically, I will discuss the exception handling framework that is in place, talking about .Net exceptions such as <b>System.Exception<\/b> and what I call &#8216;<i>CPU exceptions<\/i>&#8216; such as Access Violation (C0000005): You might know them as Win32 or hardware exceptions.\u00a0 I will then explain how we can create, and use, memory dumps to find and fix bugs after the fact; in other words, post-mortem debugging.\u00a0<\/p>\n<p class=\"MsoNormal\">Finally, I will show an example of debugging using <b>cdb<\/b> and also using Visual Studio.\u00a0 In the first article (<a href=\"https:\/\/www.red-gate.com\/simple-talk\/dotnet\/net-framework\/net-debugging-dont-give-me-none-of-your-vs\/\">Don&#8217;t Give me none of your VS<\/a>), I was advocating the practice of just using <b>cdb<\/b>, but I now realise that this is quite a big jump: In this article, therefore, I will show an example using <b>cdb<\/b> and <b>sos.dll<\/b> and then go on to discuss how you can achieve the same thing in Visual Studio although, in this particular example, you will need a degree of patience.\u00a0 However, I want to be clear in that I am not personally anti Visual Studio or Microsoft, I think it is a very good IDE, I use it every day and am happy with it, I just believe that the debugging tools for Windows give you more control and power when debugging and when you don&#8217;t have the option of installing Visual Studio (i.e. a production server) or you don&#8217;t have source code readily available then you can&#8217;t beat <b>cdb<\/b> and <b>sos.dll<\/b> for debugging managed applications.<\/p>\n<h2>What is an exception?<\/h2>\n<p class=\"MsoNormal\">Let&#8217;s start at the beginning. An exception is an event that, under normal operations, shouldn&#8217;t happen at any time, but may do. \u00a0If it is not handled, it can stop your application from running.\u00a0 An exception is analogous to your car stopping dead while you are driving. There are many possible causes for the stop; you may have applied the brake, the engine may have seized, a passenger inside the car may have yanked at the hand brake or someone external may have put something fairly solid in your way.\u00a0 Whatever has happened, if you handle the situation, some things you can recover from and some you can&#8217;t.<\/p>\n<p class=\"MsoNormal\">An exception is either raised by the CPU; something maybe like a divide by zero or access violation. This happens because the CPU has a set of rules for how an operation works: If it doesn&#8217;t like the parameters, it will shout and ask you (the developer) what it is you want to do.\u00a0 I also include soft exceptions such as user breakpoints as these will end up causing the same result.\u00a0 The second way for an exception to occur is for an application to ask Windows to raise an exception, which then does the asking rather then\u00a0 the CPU.\u00a0 To raise an exception, the application uses the win32 function <b>RaiseException<\/b>.<\/p>\n<h2>How are exceptions handled?<\/h2>\n<p class=\"MsoNormal\">To provide a framework around exceptions, Windows provides, and the CLR uses, structured exception handling.\u00a0 What happens is that you register a handler using <b>SetUnhandledExceptionFilter<\/b>, and Windows stores the methods registered in a chain ordered by how recently these were added, visiting each in turn until the exception is handled or the application is terminated.<\/p>\n<h2>What about .NET Exceptions?<\/h2>\n<p class=\"MsoNormal\">You may well be wondering why, in a .NET article, I have described what happens in a C++ Win32 application. Surely this is all old hat, and we are in the all-whizzy CLR world?\u00a0 Well the CLR is written in c++ and when your program runs, and an exception is raised, it is a CLR function that is called <b>COMPlusFrameHandler<\/b>. This is in <b>mscorwks.dll<\/b>.\u00a0<\/p>\n<p class=\"MsoNormal\">If you have the rotor or sscli \u00a0code and want to find out more about how the CLR handles exceptions, you can find it in <code>\"sscli20\\clr\\src\\vm\\i386\\excepx86.cpp\"<\/code>, this does a number of things, but of particular note is that it takes the CPU exception such as a Access Violation\u00a0 and creates an actual .NET <b>Systm.AccessViolationException<\/b> or <b>System.NullReferenceException<\/b> (it will translate a access violation into either, see <b>MapWin32FaultToCOMPlusException<\/b> in sscli20\\clr\\src\\vm\\excep.cpp).<\/p>\n<p class=\"MsoNormal\">The C<b>OMPlusFrameHandler<\/b> is also called for managed exceptions, because the MSIL code calls <b>RaiseException<\/b> which then causes the structured exception handling (SEH) to be invoked.<\/p>\n<p class=\"MsoNormal\">Whether \u00a0it is a .NET or CPU exception, the CLR, uses the JIT manager in order to find a MSIL handler for the type of exception that has been raised.\u00a0 If a handler is found, then execution continues at that point; if not, then the SEH chain is checked for further handlers.<\/p>\n<p class=\"ILLUSTRATION\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-image001.jpg\" alt=\"880-image001.jpg\" width=\"338\" height=\"770\" \/><\/p>\n<p class=\"MsoNormal\">Let&#8217;s now take a look at a memory dump file to verify this. In true showbiz style, I will use a memory dump that I made earlier. This is available for you to download, if you wish, in the links at the end of the article. \u00a0If you do, make sure you have the debugging tools for Windows.\u00a0 This first example cannot be done with Visual Studio, so it will just be in <b>cdb<\/b>.<\/p>\n<p class=\"MsoNormal\">Start a command prompt, and then run the <b>doDebug.cmd<\/b> file from the previous article and then do &#8220;<code>cdb -z c:\\pathToDumpFile\\sampleCrash.dmp<\/code>&#8220;. It should open the dump file and show something like:<\/p>\n<p class=\"ILLUSTRATION\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-better02.jpg\" alt=\"880-better02.jpg\" width=\"450\" height=\"317\" \/><\/p>\n<p class=\"MsoNormal\">This tells us that it can open the file, and that it is sitting at the point of an exception (&#8220;This dump file has an exception of interest stored in it&#8221;).\u00a0 Let&#8217;s first of all have a look at the SEH chain: so type <code>\"!exchain\"<\/code>:<\/p>\n<p class=\"ILLUSTRATION\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-Better04.jpg\" alt=\"880-Better04.jpg\" width=\"500\" height=\"127\" \/><\/p>\n<p class=\"MsoNormal\">This shows that the first handler is <b>COMPlusFrameHandler<\/b>, and then we have a number of other handlers which ultimately end up with kernel32 which, if it gets to that point, will terminate the program.\u00a0 For now we just need to understand that there is, in fact, a CLR handler (the CLR used to be called com+ for some reason I am not aware of).\u00a0 It is also important to understand that <b>COMPlusFrameHandler<\/b> internally uses <b>CPFH_RealFirstPassHandler<\/b> to actually do the work of handling the exception.<\/p>\n<p class=\"MsoNormal\">We should now load the <b>sos.dll<\/b> so do &#8220;<code>.loadby sos mscorwks<\/code>&#8220;. This should just return you to the command prompt without any errors.<\/p>\n<p class=\"MsoNormal\">Let&#8217;s take a look at some sample code:<\/p>\n<pre class=\"lang:c# theme:vs2012\">namespace SampleCrash\r\n{\r\n\u00a0\u00a0\u00a0 class Program\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 static void Main(string[] args)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 throw new System.InvalidOperationException();\r\n\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0 }\r\n}\r\n<\/pre>\n<p class=\"MsoNormal\">This raises a new exception, so why don&#8217;t we see what the MSIL looks like? First we need the method description, so do <code>\"!Name2EE * SampleCrash.Program.Main\"<\/code>. This shows the details we need:<\/p>\n<pre class=\"lang:c# theme:vs2012\">Module: 00752f2c (SampleCrash.exe)\r\nToken: 0x06000001\r\nMethodDesc: 007532c0\r\nName: SampleCrash.Program.Main(System.String[])\r\nJITTED Code Address: 007f0070\r\n<\/pre>\n<p class=\"MsoNormal\">Let&#8217;s now take a look at the MSIL code, &#8220;DumpIL 007532c0&#8221;<\/p>\n<pre class=\"lang:c# theme:vs2012\">0:000&gt; !DumpIL 007532c0\r\nilAddr = 00802050\r\nIL_0000: nop\r\nIL_0001: newobj System.InvalidOperationException::.ctor\r\nIL_0006: throw\r\n<\/pre>\n<p class=\"MsoNormal\">This creates a new<b> InvalidOperationException<\/b> and calls the MSIL function &#8220;throw&#8221; &#8211; let&#8217;s now take a look at the assembly code for this, by taking the &#8220;JITTED code address&#8221; (007f0070) and running <code>\"!U 007f0070\"<\/code>.\u00a0 Here we see that the <b>InvalidOperationException <\/b>constructor is called and then &#8220;<b>JIT_Throw<\/b>&#8220;<\/p>\n<p class=\"ILLUSTRATION\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-Better06.jpg\" alt=\"880-Better06.jpg\" width=\"600\" height=\"80\" \/>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/p>\n<p class=\"MsoNormal\">If you use the <b>sscli<\/b> code or disassemble <b>JIT_Throw<\/b> (sscli20\\clr\\src\\vm\\jithelpers.cpp or &#8220;uf JIT_Throw&#8221;) you can see that it calls &#8220;<b>RaiseTheExceptionInternalOnly<\/b>&#8221; which then calls &#8220;<b>RaiseException<\/b>&#8220;:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-Better08.jpg\" alt=\"880-Better08.jpg\" width=\"520\" height=\"58\" \/><\/p>\n<p class=\"MsoNormal\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-Better10.jpg\" alt=\"880-Better10.jpg\" width=\"550\" height=\"82\" \/><\/p>\n<p class=\"MsoNormal\">This shows us that <code>\"<\/code><code>throw new System.InvalidOperationException<\/code><code>();\"<\/code> in c# does in fact call<b> RaiseException<\/b> and shows how an exception ends up in the SEH handler.<\/p>\n<h3>How does the CLR handle exceptions?<\/h3>\n<p class=\"MsoNormal\">When the CLR exception handling is called from a CPU exception, it needs to create a .NET exception object because a managed catch block needs a managed object derived from <b>System.Exception<\/b>.\u00a0 The CLR creates a specific exception based on a simple switch statement which takes the CPU exception and decides which of the CLR exceptions to raise.\u00a0 When the exception is created, <b>CPFH_FirstPassHandler<\/b> then stores it on the managed thread&#8217;s &#8220;throwable&#8221; property.\u00a0 <b>CPFH_FirstPassHandler <\/b>is then called again and at this point because the &#8220;throwable&#8221; property has an exception object, it goes through the logic of handling it.\u00a0 When a .NET exception is raised, the &#8220;throwable&#8221; property is already set so it doesn&#8217;t need to then create the exception.<\/p>\n<p class=\"MsoNormal\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-image012.jpg\" alt=\"880-image012.jpg\" width=\"383\" height=\"408\" \/><\/p>\n<h1>Things to note when debugging<\/h1>\n<p class=\"MsoNormal\">When debugging a managed process under Visual Studio, the exception is always translated to the .NET variant i.e. a <b>System.AccessViolationException<\/b> instead of the CPU exception code that you see in <b>cdb<\/b> i.e. C0000005 so you might think you are getting a different result running under <b>cdb<\/b> to Visual Studio, but it is actually the same.\u00a0 When you debug a dmp file then, because you are debugging it as if it was an unmanaged application, it is not translated.<\/p>\n<h1>What happens if you don&#8217;t handle an exception?<\/h1>\n<p class=\"MsoNormal\">This depends on the type of application, all .NET apps have a handler higher in the SEH chain than <b>ComPlusFrameHandler<\/b> (if you want to see the chain in <b>cdb<\/b>, the command as noted earlier was &#8220;<code>!exchain<\/code>&#8220;).\u00a0 Console programs display the details of the exception and then exit.\u00a0 Windows apps close, as do services, and you may see a message written in the event log.<\/p>\n<p class=\"MsoNormal\">ASP.NET apps are most interesting because normally unhandled exceptions do not kill the process, instead they write a message to the web client, aka the yellow screen of death (this can be turned off using the web.config), a message is added to the event log and the connection is terminated but all other web clients using the same process are fine.\u00a0 Certain exceptions like a stack overflow may well cause the asp.NET worker process to crash, so don&#8217;t always expect your web app to continue running.<\/p>\n<p class=\"MsoNormal\">So, if you find that your application or service just stops running then there is a very high chance that you are getting unhandled exceptions.\u00a0 In certain versions of Windows in certain configurations, you may see the trustworthy &#8220;Dr Watson&#8221; spring into life, capture a memory dump and then ask you if you want to send it off to Microsoft to check to see if there is a known fix for it.\u00a0 If you choose to queue the dump until later (via the GUI or group policy) then you can grab it from <code>C:\\WINDOWS\\pchealth\\ERRORREP\\QSIGNOFF<\/code> where there may be a number of cab files with dump files in.<\/p>\n<h1>Memory Dumps<\/h1>\n<h2>What is a memory dump?<\/h2>\n<p class=\"MsoNormal\">A memory dump is a file containing all or part of the memory of a process. They can either be very useful or of limited use depending on how they are created, and which portions of memory they contain.<\/p>\n<h3>Process Memory<\/h3>\n<p class=\"MsoNormal\">Let&#8217;s take a quick look at how a process is laid out and how it uses memory to give us enough detail to be able to decide which type of dumps we need and why sometimes we don&#8217;t get the detail that we need.\u00a0 When you start a process, the binary CPU instructions are read from the exe or dll file and copied into memory: Then, the address of the bytes are passed to the CPU to execute.\u00a0 This is called the code portion; we need it for debugging so as to be able to tell what the current CPU command is, and where it happened.\u00a0 If we have full symbols, then we can also find out the location in the source code where the current command is.<\/p>\n<p class=\"MsoNormal\">At some point in the process, we get the space for the stacks. These store .NET value types and allow both the CPU and our debugger to keep a trace of where we are exactly; by which I mean the \u00a0method calls that led up to the current location.\u00a0 If we didn&#8217;t include the stack space in the dump, then \u00a0we wouldn&#8217;t be able to tell how we ended up at a specific location and which parameters were passed in.<\/p>\n<p class=\"MsoNormal\">The last part is the heap. This is where .NET reference and large objects get created: Without these we would know what types of objects we have but without knowing the properties of those types.<\/p>\n<h3>How are memory dumps created?<\/h3>\n<p class=\"MsoNormal\">There is an API function called <b>MiniDumpWriteDump<\/b> which helps to create memory dumps, and quite a few different applications use it to create them.\u00a0 In <b>cdb<\/b> it is simply a case of attaching to the process, and then running <code>\".dump \/ma c:\\pathToDump.dmp\"<\/code>. \u00a0The <b>\/ma \u00a0<\/b>switch causes all stack space, code and the heap to be added to the file.<\/p>\n<p class=\"MsoNormal\">Other tools are <b>DrWtsn32<\/b> (use -p then the process id), and <b>debug diag<\/b> which is used mainly for IIS based applications but can be used to create a dump of any process.\u00a0 One thing to note with <b>debug diag<\/b> is that it creates two files, one .dmp is just the stack portion, the second is called a .hdmp which includes the heap so it is of much more use.<\/p>\n<h3>Why would you debug using a memory dump?<\/h3>\n<p class=\"MsoNormal\">There are two main cases where you would probably need to debug using a memory dump. The first case is that your application has had an unhandled exception and crashed, and all you have is a memory dump.\u00a0 The second case is where you get an exception, or a specific behaviour in a production environment, and you can&#8217;t leave a debugger attached while you troubleshoot as it could interrupt the user service.\u00a0 Instead you could attach <b>cdb<\/b>, create the dump file at the right place and then detach the debugger, this would mean that the application continues with only a small interruption in service. Of course, depending on your environment, this is not always possible but can be sometimes be your only option.<\/p>\n<p class=\"MsoNormal\">Let&#8217;s take a practical look at debugging using a memory dump in <b>cdb<\/b> and Visual Studio.\u00a0 This is from the example2.exe application which is attached to the article.\u00a0 It has a number of options but the one we will look at highlights why <b>cdb<\/b> is faster than Visual Studio.<\/p>\n<p class=\"MsoNormal\">First, you should start a command prompt and change to the directory with the debugging tools, then run the <code>\"doDebug.cmd\"<\/code> file as in the previous article (also attached in the zip file).\u00a0 Then &#8220;<b>cdb -z c:\\pathToDumpFile\\stackOverflow.dmp&#8221;.<\/b>\u00a0 This should open as per:<\/p>\n<p class=\"ILLUSTRATION\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-Better13.jpg\" alt=\"880-Better13.jpg\" width=\"630\" height=\"425\" \/><\/p>\n<p class=\"MsoNormal\">This shows that we have a mini dump with full memory, so we have the portions we need.\u00a0 We have an exception, in this case a &#8220;Stack overflow&#8221; exception.<\/p>\n<p class=\"MsoNormal\">We know we have a stack overflow but we don&#8217;t know if this is a managed or unmanaged problem, so let&#8217;s get a native stack trace &#8220;kf&#8221;<\/p>\n<p class=\"MsoNormal\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-Better15.jpg\" alt=\"880-Better15.jpg\" width=\"580\" height=\"185\" \/><\/p>\n<p class=\"MsoNormal\">This shows that the <b>mscorwks!CallDescrWorker<\/b> method called a unknown method.\u00a0 The reason it is unknown is that the debugger uses the module list to determine the name of the module (do &#8220;lm&#8221; to get a module list) &#8211; because the CLR JIT&#8217;s the MSIL into assembly then there is no actual module as it is hanging around somewhere in the process.<\/p>\n<p class=\"MsoNormal\">Because mscorwks called a unknown function, then this is very likely to be a managed problem.\u00a0 In the stack trace above, I used kf as this shows us how much memory each stack frame is using. It actually works out the distance between two frames so the first doesn&#8217;t have a memory usage.\u00a0 The reason the memory is important is that there are two types of stack overflows; the first is when you create too many, or too large, objects on the stack; and the second is when a function recurses and uses up all of the memory.\u00a0<\/p>\n<p class=\"MsoNormal\">So where are we? we know that it is likely to be a managed code problem, so let&#8217;s load <b>sos.dll<\/b> &#8220;.<b>loadby sos mscorwks<\/b>&#8221; and let&#8217;s get a stack trace.\u00a0 Note that, because this is a problem with recursion, if you do a <code>\"!CLRStack\"<\/code> the debugger will go mad showing frame after frame &#8211; in <b>cdb. <\/b>To stop it do &#8220;Ctrl+C&#8221; and it will interrupt the trace.\u00a0 A tip for using <b>cdb<\/b> is that, if you need to do something that will output a lot of data, minimise the window and it will take no time at all.<\/p>\n<p class=\"MsoNormal\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-Better17.jpg\" alt=\"880-Better17.jpg\" width=\"420\" height=\"329\" \/><\/p>\n<p class=\"MsoNormal\">So we now have a stack trace showing the name of the function that is causing the stack overflow: If we have the source code we can examine it and see what might be going on, but let&#8217;s take a quick look at the MSIL for fun.<\/p>\n<p class=\"MsoNormal\">As always, we need to get the method description for the helper method;\u00a0 so we get the method table of the <b>StackOverflow<\/b> class by doing <b><code>\"!Name2EE * example2.StackOverflow<\/code><\/b>&#8220;.\u00a0 Then we take the value from &#8220;<b>MethodTable<\/b>:&#8221; and do <b>&#8220;!DumpMT -md 019631a4&#8221;<\/b><\/p>\n<p class=\"MsoNormal\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-Better19.jpg\" alt=\"880-Better19.jpg\" width=\"460\" height=\"432\" \/><\/p>\n<p class=\"MsoNormal\">Then, to get the MSIL, do &#8220;!<b>DumpIL 001963190<\/b>&#8221; and we get:<\/p>\n<p class=\"MsoNormal\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-better21.jpg\" alt=\"880-better21.jpg\" width=\"450\" height=\"234\" \/><\/p>\n<p class=\"MsoNormal\">So this is interesting, <code>\"ldarg.1\"<\/code> grabs the first parameter, &#8220;<b>ldc.i4.1<\/b>&#8221; grabs the value 1 and the <code>\"add\"<\/code> adds them together; so it is incrementing some sort of counter, and then it is checking the result against <b>_max_RecurseLevel<\/b> and if it is greater than or equal to it then it quits the function (<code>\"bge.s IL_0016\"<\/code>).\u00a0 This is a fairly simple example, but now all we need to do is have a look at <b>_maxRecurseLevel<\/b> and the value passed in to see where we are.<\/p>\n<p class=\"MsoNormal\">Incidentally, these are the links for the msil documentation, when you don&#8217;t understand what the msil is doing, it is fairly simple to use msdn to see what each operator does:<\/p>\n<p class=\"MsoNormal\">Ldarg.1 <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.reflection.emit.opcodes.ldarg_1.aspx\">http:\/\/msdn.microsoft.com\/en-us\/library\/system.reflection.emit.opcodes.ldarg_1.aspx<\/a><\/p>\n<p class=\"MsoNormal\">Ldc.i4.1 <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.reflection.emit.opcodes.ldc_i4_1.aspx\">http:\/\/msdn.microsoft.com\/en-us\/library\/system.reflection.emit.opcodes.ldc_i4_1.aspx<\/a><\/p>\n<p class=\"MsoNormal\">Bge_s <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.reflection.emit.opcodes.bge_s.aspx\">http:\/\/msdn.microsoft.com\/en-us\/library\/system.reflection.emit.opcodes.bge_s.aspx<\/a><\/p>\n<p class=\"MsoNormal\">Add <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.reflection.emit.opcodes.add.aspx\">http:\/\/msdn.microsoft.com\/en-us\/library\/system.reflection.emit.opcodes.add.aspx<\/a><\/p>\n<p class=\"MsoNormal\">Ok so let&#8217;s get back to looking at where we are and what parameters are passed in. Get \u00a0ready with ctrl+c again and do <b><code>\"!CLRStack -a<\/code><\/b>&#8221; to show all parameters and local variables:<\/p>\n<p class=\"MsoNormal\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-Better23.jpg\" alt=\"880-Better23.jpg\" width=\"380\" height=\"258\" \/><\/p>\n<p class=\"MsoNormal\">Notice how the &#8220;this&#8221; pointer is passed as a parameter, it is always first, also note how we only see it on the top method.\u00a0 This is because the CLR optimizes the code and instead of passing the reference on the stack which would use up more space, it stores it in a register and uses that instead.\u00a0 It is a CPU level optimization that means your application is faster but debugging can sometimes be harder.\u00a0 Let&#8217;s now dump out the value of &#8220;this&#8221; by doing <code>\"!do 0x01ff66a0\"<\/code><\/p>\n<p class=\"ILLUSTRATION\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-Better25.jpg\" alt=\"880-Better25.jpg\" width=\"640\" height=\"241\" \/><\/p>\n<p class=\"MsoNormal\">This shows us that <b>_maxRecurseLevel<\/b> is 1 million, which is probably too high, so we know what we need to do to fix it.\u00a0 If we want to guess an accurate figure to use then we can see the current value of the other parameter which we know increments by one each time it is run to see how many we have.\u00a0 The value on the first stack frame is <code>\"i = 0x0001f88c\"<\/code> so we just need to translate that hex number into something readable &#8220;? 0x0001f88c&#8221;<\/p>\n<p class=\"MsoNormal\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-better27.jpg\" alt=\"880-better27.jpg\" width=\"300\" height=\"45\" \/><\/p>\n<p class=\"MsoNormal\">So we know it bombs out on around 130 thousand recursive calls.<\/p>\n<p class=\"MsoNormal\">What if we wanted to know how it got into the recursive function? \u00a0Well we have no choice but to do a <code>\"!CLRStack\"<\/code> and let it finish, I would suggest adding -a so you get all the parameters and also minimising the window after you do it (remember it has 129164 frames to dump, before it gets to the rest of the code!)<\/p>\n<p class=\"MsoNormal\">If you wish to run, <code>\"!CLRStack -a\"<\/code> and when this has finished, which will take a moment or two, you should get:<\/p>\n<p class=\"MsoNormal\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-Better29.jpg\" alt=\"880-Better29.jpg\" width=\"420\" height=\"347\" \/><\/p>\n<p class=\"MsoNormal\">This shows us that the Main method called our helper &#8211; this isn&#8217;t strictly true if you look at the source code. Because it is a release build, a lot of code gets optimized out and also the values of many parameters have gone as well.\u00a0 To see all the values that are readily available and stored on the stack, or have a reference on the stack, do <b><code>\"!dso\"<\/code>.<\/b>\u00a0 Using all this information we should have enough information to track down the bug and fix it.<\/p>\n<p class=\"MsoNormal\">As promised, I said I would cover the example where possible in Visual Studio 2008. If you start up Visual Studio, go to file \u00e0 open solution and browse to the dmp file.\u00a0 When it has loaded, go to the solution explorer and right-click the dump file. Then \u00a0choose &#8220;Debug \u00e0 Step into new instance&#8221;.\u00a0 When this starts, you will be prompted with the exception a &#8220;Stack overflow&#8221; so we know what went wrong.\u00a0 If you click <code>\"break\"<\/code> you can get into the debugger.<\/p>\n<p class=\"MsoNormal\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-image031.png\" alt=\"880-image031.png\" width=\"584\" height=\"654\" \/><\/p>\n<p class=\"MsoNormal\">Things to note are that the call stack is wrong, it just shows one function which is obviously not right and it shows a page of disassembly, but it isn&#8217;t easy to see where you are. To find the current line you need to show the registers window, and look at the value for <b>eip<\/b> which gives the address you are currently at..<\/p>\n<p class=\"MsoNormal\">So we are unable to get a native stack trace to see where we are. Instead, let&#8217;s just go ahead and load the <b>sos.dll<\/b> and get a <code>\"!CLRStack\"<\/code>.\u00a0 If you open the command window (View\u00e0Other Windows\u00e0Command Window) when this opens, if you have a &#8220;&gt;&#8221; prompt then type <code>\"immed\"<\/code> to get into the immediate mode.<\/p>\n<p class=\"MsoNormal\">If you then type <code>\".load sos\"<\/code> &#8211; I have to admit here that the syntax is indeed easier in Visual Studio to load <b>sos.dll<\/b> than in <b>cdb<\/b>.\u00a0 This should show that the dll is loaded, now do <code>\"!CLRStack -a\"<\/code>: \u00a0But be warned it will take a long time to complete, and while it is doing it you won&#8217;t be able to use it or stop it unless you kill Visual Studio.\u00a0 I have always killed Visual Studio after about 20 minutes, if you have a faster machine or more patience then it might well finish.<\/p>\n<p class=\"MsoNormal\">When it has finished, you can continue from where we get the trace in <b>cdb<\/b> so <b>&#8220;!Name2EE * example2.StackOverflow&#8221;<\/b> and take the value from &#8220;<b>MethodTable:&#8221;<\/b> and do <b><code>\"!DumpMT -md 019631a4<\/code><\/b>&#8221; which then gives you the method description, which you can then run <b><code>\"!DumpIL\"<\/code><\/b> against.<\/p>\n<p class=\"MsoNormal\">Obviously this was a demo rigged in <b>cdb<\/b>&#8216;s favour but Visual Studio really is slower and there are other times when it is noticeably so. Another one that I will go into further in a future article is the wonderful command <code>\"!DumpHeap -stat\"<\/code> &#8211; this is what we use to track down memory leaks as it shows a list of all the different types of objects and how much memory they are using so you can see at a glance exactly where your memory is going.\u00a0 Let&#8217;s do <code>\"!DumpHeap -stat\"<\/code> in <b>cdb<\/b>:<\/p>\n<p class=\"ILLUSTRATION\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-Better33.png\" alt=\"880-Better33.png\" width=\"630\" height=\"315\" \/><\/p>\n<p class=\"MsoNormal\">This shows us all the objects ordered by increasing memory usage, so the further down the list the more memory that type is using.\u00a0 In this view we get the method table, the count and also the total size.\u00a0 I have highlighted <b>example2.StackOverflow<\/b> because it is another simple way to get the details of a class that we want to explore further, in this case we have one instance of it so it is trivial, if it was <b>System.String,<\/b> or an often-used class, then there would be more work involved in tracking down the right one.\u00a0 To find specific instances of classes do <code>\"!DumpHeap -type example2\"<\/code> (or -type example2.StackOverflow, as it is a substring match, both will work):<\/p>\n<p class=\"MsoNormal\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-better35.jpg\" alt=\"880-better35.jpg\" width=\"420\" height=\"109\" \/><\/p>\n<p class=\"MsoNormal\">If you did <b>!DumpHeap -type System.String<\/b> or some other class then, as mentioned, there would be far more than one listed.\u00a0 If we want to view the object we simply do <b>&#8220;!do 01ff66a0&#8221;<\/b> which is the address of the object and again we can see the value of _maxRecurseLevel:<\/p>\n<p class=\"ILLUSTRATION\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/880-better037.jpg\" alt=\"880-better037.jpg\" width=\"630\" height=\"217\" \/><\/p>\n<h1>Summary:<\/h1>\n<p class=\"MsoNormal\">I have covered quite a range of topics in this article and hopefully have explained how the CLR handles exceptions in the context of the unmanaged runtime.\u00a0 It is important to understand how it works, because the use of exceptions within your own code is such a fundamental part of .NET programming; understanding how it works will help when you are debugging an issue in <b>cdb<\/b> and you are not even getting .NET exceptions.<\/p>\n<p class=\"MsoNormal\">If \u00a0you can take a memory dump from a customer or a live production server, then it is such an easy way to fix problems because you can easily see the cause of a crash or other event. If you want an example of how these are used, Microsoft has a service where, when you get a crash, it can suggest a kb or support page to help solve the issue. Dr watson (dw20)\u00a0 can take a memory dump of the process, and this dump is then uploaded to their servers; then stacks are analyzed against known issues to automatically redirect you to a kb or support page to help solve the issue.\u00a0 Microsoft reviews the most common crashes in each product, and it is a very good way for them to fix issues that are actually affecting users. If you supply software yourselves, then I would recommend adding something to your products so you can get user memory dumps as and when necessary.<\/p>\n<p class=\"MsoNormal\">As for <b>cdb<\/b> \/ Visual Studio, I believe if you take the time to learn how the debugging tools for Windows work, you will find the effort pays off. \u00a0I can&#8217;t promise that you will need to use the skills regularly, but I will guarantee that, at some point, they will be invaluable.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Memory dumps are a wonderful way of finding out what caused an exception in a managed .NET application, particularly if it is happening in a production application. It is when tracking exceptions in applications where you can&#8217;t use Visual Studio that the techniques of using cdb and sos.dll come into their own. They may nor be skills that you need to use regularly, but at some point, they will be invaluable. Edward supplies sample memory dumps and gives you a simple introduction.&hellip;<\/p>\n","protected":false},"author":59464,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538],"tags":[4143,4229],"coauthors":[11314],"class_list":["post-744","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","tag-net","tag-net-framework"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/744","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/59464"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=744"}],"version-history":[{"count":7,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/744\/revisions"}],"predecessor-version":[{"id":73815,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/744\/revisions\/73815"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=744"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=744"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=744"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=744"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}