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 |
cdb | Console | Yes | Limited (sos.dll) | No | Yes |
cordbg | Console | No | Yes | No | Yes |
dbgclr | GUI | Limited | Yes | No | No |
kd | Console | Yes | Limited (sos.dll) | Yes | Yes |
mdbg | Console | No | Yes | No | No |
ntsd | Console | Yes | Limited (sos.dll) | No | Yes |
Visual Studio | GUI | Yes | Yes | No | Yes |
windbg | GUI | Yes | Limited (sos.dll) | Yes | Yes |
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: cdb
, kd
, ntsd
and 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 cdb
and ntsd
offer only user-mode debugging. Actually, cdb
and 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 dbgclr
.
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 mdbg
. Like mdbg
, 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
. 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 cordbg
and 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 !CLRStack
and !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
windbg
andkd
and 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.
Links
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
dbgclr
andmdbg
- 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
No comments:
Post a Comment