A colleague of mine informed me that she had been working on a hard to track down bug in an application written by another developer. After some investigation she discovered the bug was caused by invalid logic created by an exception that the original developer had decided to swallow.
This scenario is quite common and is documented as a common source of bugs in the excellent book Debugging Microsoft .NET 2.0 Applications by John Robbins. It would probably be better if the debugger breaks on all exceptions by default with Just My Code, that way those hidden bugs would become more apparent during development.
In order to get the debugger to break on all CLR exceptions all you need to do is the following:
- From the Debug Menu choose Exceptions or CTRL-ALT-E (screenshot from VS.NET 2008):
Select Thrown for all CLR exceptions or expand the tree view to only break on specific exceptions. You can then debug your app and hopefully (if it is well written), the debugger shouldn’t normally hit anything that isn’t a breakpoint!
This Visual Studio debugger feature is useful for a number of scenarios, notably:
- Ensuring that the application is not catching overly general exceptions.
- Locating difficult to detect bugs (these can also be caused by 1).
- Optimizing performance.
Of these 3 scenarios optimizing performance is worth discussing. When I first learnt about this feature, I tried it out on a large application that I was assigned the task of maintaining (disclaimer- I wasn’t in the original programming team :-).
The application was a .NET 1.1 application (I was in the process of upgrading to 2.0- as I always strive to upgrade to the latest available framework/toolset where possible/feasible) that conceptually did something along the lines of:
// Assign the string from somewhere...
int result = 0;
result = int.Parse(hopefullyANumber);
This code would not of caused any real performance issues, were it not for the fact that it was being called over and over thousands of times!
Admittedly the original developers didn’t have access to Int32.TryParse (but they could of used other techniques such as regular expressions), however after modifying the code so that it used TryParse I managed to reduce the CPU usage of the application by over 20% (I profiled it before and after with dotTRACE)!
It is good practise to see if the TryParse or Tester-Doer pattern can be of benefit to the performance of your application.
In summary having the debugger break on all exceptions in applications is a useful technique to catch bugs early in development, to check for over generalized exception handling or to enhance performance.