flow.
"Flow is a condition of deep, nearly meditative involvement." - Tom DeMarco

Turn on 'all exceptions' and watch the fireworks fly

Thursday, February 15, 2007 9:44 PM

Here's a surprisingly little known tip for improving the stability of your .NET code.  When you're debugging with Visual Studio, the default settings only allow the debugger to break on exceptions which are 'unhandled', meaning exceptions that usually bubble up to the top of the application stack, resulting in that really ugly "Unhandled Exception Occurred" dialog box.

I'm sure you're thinking that this is exactly what you want, right?  Why would you care about exceptions that are caught?  Well, let me pose this question to you...how many times in your codebase have you seen this...

            try
            {
                MySubRoutine();
            }
            catch
            {
                // This method sometimes throw a null reference.  I don't really
                // know why but we'll just catch it here.
            }

Did you catch what just happened here?   The developer knew that the method call within the try block occasionally throws a null reference exception, so to be safe he just put the whole thing inside of a generic catch handler.  Now, for the sake of argument we'll not talk about the fact that the developer isn't worrying about why the exception is being thrown, only that it is.  The problem we're concerned with right now is the "catch" statement.  This catch handler will definitely handle our null reference exception, no question there.  But what happens if our rogue method generates a different type of error.  Or what happens if one of our other methods throws an exception?  Even worse yet, what happens if an unexpected exception occurs in Subroutine()?  Well, what will likely happen is that the error will be quietly swept under the rug by the general exception handler and you'll spend hours trying to figure out why some button in the GUI 15 layers up seems to do absolutely nothing when you click it.  Not that I'm speaking from experience or anything....

As you can imagine, the best defense for this is to just never catch general exceptions and, as a rule, to never catch an exception that you're not prepared to handle.  However, in the real world this doesn't always happen.  We inherit legacy code that has these general exception catches spread everywhere like a virus, we use third party open source libraries that do this inside of them and as a last ditch effort to keep exceptions from exiting the code we build APIs that have restrictions like "exceptions should never pass reach above this level".  There is hope, however.

If you're debugging you can let Visual Studio tell you whenever an exception is thrown.  This will allow you to break every time something goes wrong and make sure that what you think is happening in an exception handler really is happening in an exception handler.  Under the "Debug" menu, click "Exceptions...".  Odds are your "Thrown" column will be empty, click them on (you choose if you only want to look for certain types of exceptions or click on all of them) and watch the magic happen.

This can be a lifesaver when you're trying to figure out what's going on with a button that just seems to "die" or why that exception you're throwing in you business layer never seems to be properly handled but never seems to reach the top of the application either.

Try it once, you'll probably be amazed what's going wrong deep in the bowels of your application.  You may have an application that seems perfectly stable and happy on the surface while underneath it all it's a tumultuous mess.  Why do you care if the app seems fine in the big picture?  Well, for one, those exceptions are expensive!  Every time an exception is thrown thats one little more hiccup your app must endure.  Some of these you hiccups you may have to live with, but you'd be surprised how easily others can be corrected.  Are you getting a lot of FileNotFoundExceptions?  Check if the file exists with File.Exists(string) before you try to use it?  Getting a lot of NullReferenceExceptions?  Do a quick (if object != null) before you start calling against it.  You'll be amazed how easily you can eliminate some of the most common exceptions inside your app.

kick it on DotNetKicks.com

Feedback

 re: Turn on 'all exceptions' and watch the fireworks fly

Nice to know. Never noticed that option. 2/24/2007 4:11 PM | Anders J, DK

 re: Turn on 'all exceptions' and watch the fireworks fly

Nice tip. Thanks! 6/4/2007 5:50 AM | Jas

# re: Turn on 'all exceptions' and watch the fireworks fly

If you cannot find the 'Exceptions...' menu in Debug (as in my case with VS Team Suite) do the following:

* Right-click an empty space on the toolbar
* Select 'Customize...' at the buttom of the menu. This is used to customize the toolbars.
* Under the 'Commands'-tab, locate 'Debug' and you should find a button called 'Exceptions...'
* Drag this button onto an empty space in the toolbar.

You can now easily customize exceptions, and follow the tips on this page.

Cheers! 2/6/2008 8:52 AM | Thies Schrader, Conceptos IT Dev

# re: Turn on 'all exceptions' and watch the fireworks fly

Thanks for the tip, Thies!

Some of my coworkers have noticed that menu option isn't always available on a new install, as well.

With default C# keybindings enabled, you can also try Ctrl+Alt+E to bring this window up. 2/6/2008 8:59 AM | Jeremy

 re: Turn on 'all exceptions' and watch the fireworks fly

I know this trick and it's very usefull. My "select all" option is always on to be aware of any hiddent problems. But....
Some thrown exceptions cannot be worked around (some of them are thrown and handled in .NET library itself!) and I would like to mark a section of code where i could say to the debugger "please, don't border me if any exception happens here...". You guys have any clue how to make that ?
3/27/2008 4:37 PM | Etienne

# re: Turn on 'all exceptions' and watch the fireworks fly

Unfortunately not right off hand. I've tried to work around the same problem (I have a piece of SCOAB that constantly throws FileNotFoundExceptions on a 2-second poll) but never found a good answer.

Here are two things to try...
1) You can set TracePoints at the entry point to the bad code that trigger macros. TracePoints are like BreakPoints except they don't necessarily cause the code to pause (thing of them like checkpoints). Then you can write a macro that temporarily disables first chance exceptions and another TracePoint at the other end that re-enables them. I tried this once and got the macros triggered but never figured out a way to programmatically activate the exceptions (I'm also not sure if you could do it without showing the dialog either).

2) You may also want to try a DebuggerNonUserCodeAttribute (http://msdn2.microsoft.com/en-us/library/system.diagnostics.debuggernonusercodeattribute.aspx). This attribute is used to tag sections of code that you want to the debugger to automatically step over. For example, most designer or WSDL.exe generated code is tagged with this so you won't actually step into the generated source code each time you try to debug. I'm not sure, however, if this keeps the debugger from stopping on exceptions that occur in that section of code. It may be worth a try, though.

Good luck!
Jeremy 3/29/2008 10:50 AM | Jeremy

Post a comment





 

Please add 8 and 7 and type the answer here: