Thursday, 11 June 2015

Managed Debugging Assistants

I was reading a copy of Jeffry Richter’s book CLR via C#today, and came across this note on p.538 “The .NET Framework offers a feature called Managed Debugging Assistants (MDAs). When an MDA is enabled, the .NET framework looks for certain common programmer errors and fires a corresponding MDA.”

What? I have I been living under a rock? Why hadn’t I heard of these before?

Well it turns out these have been around since .NET 2.0 (Visual Studio 2005), and you’ll find the list of available MDAs in the Exceptions dialog (Debug | Exceptions)

Visual Studio 2013 Exceptions Dialog

or in 2015 in the (new and improved non-modal) Exception Settings window (Debug | Exception Settings).

Visual Studio 2015 Exception Settings window

I must confess virtually the only time I visit this dialog/window is to expand Common Language Runtime Exceptions when I want to modify which exceptions the debugger automatically should Break When Thrown, so may be that’s why I’ve overlooked them.

The MDAs enabled by default in Visual Studio are:

  • CallbackOnCollectedDelegate
  • ContextSwitchDeadlock
  • DateTimeInvalidLocalFormat
  • DisconnectedContext
  • FatalExecutionEngineError
  • InvalidFunctionPointerInDelegate
  • InvalidMemberDeclaration
  • InvalidVariant
  • LoaderLock
  • NonComVisibleBaseClass
  • PInvokestackImbalance
  • RaceOnRCWCleanup
  • Reentrancy
  • You can also see the complete list and find out more about MDAs at Diagnosing Errors with Managed Debugging Assistants. MDAs are actually built in to the CLR and and as such aren’t user-extensible. Stephen Toub described them as “Asserts in the CLR and the base class libraries that can be turned on or off”.

    So while I don’t think I was consciously aware of them, it’s possible I have see the odd MDA exception dialog – but probably just didn’t noticed the difference from the usual exception dialog. Here’s an example of the BindingFailure MDA:

    BindingFailure Managed Debug Assistant dialog

    Bringing things full circle, it turns out that there’s a StreamWriterBufferedDataLost MDA which is what Jeffrey went on to highlight as a way to identify the problem where you’ve got a StreamWriter that didn’t get a chance to flush data to the stream before it was finalized (say because the underlying stream itself was already disposed).

    This MDA is not enabled by default, so it might be something worth doing if your code makes use of StreamWriters. Note: this is a debugging feature – it only works when you’re debugging an application. There may be other MDAs that you might benefit from enabling, depending on the kind of things your code is doing.

    In some ways, MDAs are a bit like a debugger-time version of FxCop (or FxCop’s probable replacement - the new Roslyn .NET Analyzers and Code Aware Libraries).

    No comments: