Many times, debugging isn't so much about finding a bug as it is identifying performance related issues. High numbers of handled exceptions, large working sets, and the like can all lead to the perception of buggy code. At some point in our careers, most all of us have encountered bug reports stating that our application was too slow, used to much RAM, etc. Hopefully, this week's installment of debugging with cordbg can help you to quickly and easilly identify the cause of these issues and help to mitigate them where possible.
Commands used Exceptions
By default, cordbg catches all unhandled ("second chance") exceptions. To catch all exceptions - including "first chance" (handled) exceptions - use the ca[tch] command "ca e".
CorDbg's catch command can help reduce the information flood by allowing you to limit what is caught. Lets say that you have an applicaiton that occasionally encounters a SocketException. Though your application handles the exception gracefully, you want to investigate the scenarios which generate the exception. To do this, you can instruct cordbg to catch every occurance of a SocketException using "ca e System.Net.Sockets.SocketException". Please note, that like with most things in cordbg, you must be sure to fully qualify the exception type name and remember that almost everything is case sensitive.
If you would like to catch more than just a specific exception, perhaps all exeptions defined in your custom assembly, you can instruct cordbg to catch exceptions by assembly name: "ca e mscorlib.dll".
Once caught, you can explore the exception object (inner exception details, etc), walk the stack, anything you need to identify the root cause of the exception.
You can instruct cordbg to stop catching exceptions using the ig[nore] command. This can be very useful if find yourself drowning in exceptions (perhaps you enabled catching of all exceptions). You can disable breaking on all first chance exceptions using "ig e". As with catch, you can also ignore by exception type (ex: "ig e System.Net.Sockets.SocketException") and by assembly (ex: "ig e mscorlib.dll").
If you have been following the earlier posts in this series, you know that I am an advocate for enabling display of module load events. If you would like to have the debugger break into your application when your a module is loaded (either by your code or by an assembly used by your code), the ca[tch] command gives you what you need. The "ca m" command instructs cordbg to stop execution whenever a module gets loaded. You can then investigate which piece of code caused the load and why. The ig[nore] command is used to turn this feature off: "ig m".
If you have looked at the online help for cordbg (? command), you may have noticed that it can also break on class load events. Unfortunately, the NetCF runtime does not send class load events, so this feature is unavailable to when debugging on the .NET Compact Framework.
Similarly to module load events, the ca[tch] command enables the stopping of execution when a thread is started ("ca t") while ig[nore] ("ig t") toggles this feature off.
As you can see, the ca[tch] and ig[nore] commands are quite simple to use and can save valuable time investigating a good number of issues. For more information on using cordbg with NetCF applications, please see the previous posts in this series.
Until next time...
This posting is provided "AS IS" with no warranties, and confers no rights.
Some of the information contained within this post may be in relation to beta software. Any and all details are subject to change.