One thing Windows programmers cannot complain about is a lack of debugging support. Microsoft produces its own debuggers, for both managed and unmanaged scenarios, and they offer just about everything you could ask for (including scriptability and extension hooks for when they don't immediately offer what you want). Here's an overview of all the debuggers available, with a feature matrix, which is intended to be complete.
|Name||Console/GUI||Unmanaged code||Managed code||Kernel debugging||Remote debugging|
Why are there so many debuggers, and which one should you pick? There's a lot of overlap in features.
Let's start with the native debuggers:
windbg. These are all part of the Debugging Tools for Windows package.
The native debuggers excel at debugging unmanaged code, but debugging managed code is a little clumsier as support is provided only through extensions (more on that later). The most feature-complete of them is
windbg, which has a GUI as well as support for both kernel- and user-mode debugging.
kd offers only kernel-mode debugging (but you can run one of the user-mode debuggers on top of it) while
ntsd offer only user-mode debugging. Actually,
ntsd are essentially the same debugger, the only difference being that
cdb will use the same console window it was started in (if any) while
ntsd will always open a new console window. Aside from the split between kernel-mode and user-mode, which native debugger you use is mostly a matter of preference.
All native debuggers have extensive support for remoting, from having them act as dumb clients to the remote debugger to having the debugger on your end do symbol lookup as well (which can come in very handy if you cannot install or download symbols on the remote machine) and even the ability to debug processes on multiple machines simultaneously (to diagnose network protocol problems, for example).
The managed debuggers are a more varied bunch. The most important one (and for many developers the only one they know) is Visual Studio, which has its own integrated debugger. This debugger is capable of debugging both managed and unmanaged code and has a very complete GUI for both, including runtime expression evaluation of both managed and unmanaged expressions. It has some support for extensions DLLs, the same kind used by the native debuggers to provide enhanced debugging commands. Traditionally, remote debugging with Visual Studio has been rather error-prone and difficult to set up, but VS 2005 and 2008 have improved on matters by making it as simple as running a program from a remote share (at least for machines in the local network). VS has no support for kernel debugging.
dbgclr is an odd little duck that's only installed with the .NET 2.0 SDK, and nothing else (not even a full install of Visual Studio itself). Basically,
dbgclr is a slimmed-down extract of the Visual Studio 2005 debugger — it's only the debugger and nothing else. Moreover, it's only the part that can debug (pure) managed code — mixed-mode debugging is not supported. Remote debugging isn't supported either. There's nothing
dbgclr can't do that one of the other debuggers can't do better, but it beats Visual Studio in that the SDK install is at least marginally smaller (and does not require a license), so if you absolutely must have a managed debugger with a GUI but can't afford to install VS you could consider using
cordbg is also included with the Framework SDK and with the Windows SDK (or Platform SDK). It started out (in .NET 1.0) as a demonstration and bare-bones implementation of the CLR debugging interfaces, but it has basically evolved to being a skin for
mdbg (coming up next). If you're not already used to how
cordbg works, there's not much point in starting with it, since additional effort will mostly go into
cordbg is a console-mode application.
mdbg is the main managed debugger after Visual Studio. It, too, is installed with both the Framework SDK and the Windows SDK. It's a console-mode debugger with a command syntax that is unfortunately completely different from that of the native debuggers, so knowing those won't help you get started with
mdbg cannot debug unmanaged applications, though it has support for disassembling unmanaged code (mostly to diagnose problems with JIT compilation). However, debugging managed code is much more comfortable than doing it with the extensions of the native debuggers. It has no support for remote debugging.
Mike Stall wrote up an excellent summary on the relative positions of the managed debuggers. That post is two and a half years old at the time of writing this, but it's still accurate in the sense that nothing much has changed. In particular, when he mentions that they'd like to stop shipping
cordbg and even drop
mdbg once the native debuggers get integrated support for unmanaged code, keep in mind that both
mdbg are still updated, and the native debuggers still have to make do with extensions.
I mentioned earlier that the native debuggers have some support for managed debugging through extensions. The extension in question is SOS.dll (short for "Son of Strike" — Jason Zander explains the name in his post on using SOS). By loading SOS, a whole host of commands for managed debugging become available which range from useful to indispensable. Because the default native commands don't know anything about managed code, their output is not always useful. For example, the
k command decodes a call stack, but cannot handle managed frames;
u will unassemble code but cannot resolve calls to JIT-compiled code to symbols. SOS offers replacements in the form of
!u, respectively. A full list of commands is available in the MSDN.
With all these tools at your disposal, which debugger(s) should you use? I prefer to think of it as order of preference:
- Use Visual Studio if you can. It's by far the easiest to use and offers a wide range of features. For debugging managed code, it's unsurpassed in ease of use.
- For advanced scenarios, like debugging mixtures of managed and unmanaged code (like interop scenarios), network protocol debugging and tracking down handle leaks and heap corruption, the native debuggers with SOS.dll are the most powerful. Visual Studio will quickly become frustrating to use in these scenarios.
- For kernel debugging, you'll use
kdand like it.
This is by no means the full story on Windows debugging. I've left out things like Managed Debugging Assistants (MDAs), extending the managed debugging framework, Visual Studio's support for native debugger extensions, third-party debuggers, and profiling (which is not unrelated to debugging). For more information, check out one of the dedicated blogs in the links section.
Here's a list of the most important links in the article, plus some useful ones that weren't mentioned.
- Debugging Tools for Windows, containing all the native debuggers and documentation
- .NET 2.0 Framework SDK, containing
- SOS Debugging Extension (SOS.dll)
- If broken it is, fix it you should—focuses on ASP.NET debugging, but almost everything mentioned is generally applicable
- Junfeng Zhang's Windows Programming Notes
- Microsoft Advanced Windows Debugging and Troubleshooting