Despite the best documentation, stepping into the actual source code of third-party libraries can be the fastest way to diagnose a difficult bug or determine the state that a component needs to be in before a certain operation can be completed. With a little set-up magic, developers can step into libraries quickly and easily.
The first step in enabling source code step-through with MFC/ATL and the C/ C++ Runtime Libraries (CTR) is to ensure that the source code is installed when Visual Studio is installed. Figure 1 shows the Visual Studio installer options for source code installation. There are separate nodes for CRT and ATL/MFC installation, and granular control of source code installation based on character byte width and thread safety is also available. With the source code successfully installed, the options shown in Figure 2 should be displayed.
Figure 1: Installing the Visual C++ Source Code Libraries
Figure 2: Visual C++ Source Code Library Paths
With the options shown in Figure 1 and Figure 2 set, stepping into the CRT and MFC/ATL source code is extremely simple—the compiler treats the library source code the same as other source code for the project, and stepping into a CRT, ATL, or MFC method can be accomplished with a simple Step-Into Debug command. If the Microsoft Symbol Server (covered in this article) is configured to bring down debug symbol information, it is important that the PDB files that install as part of Visual Studio and the Visual Studio Service Packs are configured to be searched before the Microsoft Symbol Server. The debug symbols that the Microsoft Symbol Server brings down have the source code information stripped out of them, and if these are loaded in preference to the debug symbol files that ship with Visual Studio and its Service Packs, stepping into the CRT, MFC and ATL source will not be possible. The correct settings for the symbol file location are shown in Figure 3.
Figure 3: Symbol File Location
If the debug symbol files have been downloaded from the Microsoft Symbol Server previously, it is necessary to delete the symbol files from the local cache as well as adding the c:\windows\symbols\dll path to the symbol search path. The Module debug Window can be used to inspect where the debug symbols for a particular DLL have been loaded from, and whether they contain source code information. Figure 4 shows the Modules window with this information displayed.
Figure 4: Module Debug Window
Visual C++ 2008 Service Pack 1, which contains the MFC Feature Pack (see these two previous articles for coverage of the MFC Updates and TR1 enhancements) in addition to a number of bug fixes, contains updates debug symbol files and source code files that allow all the new Feature Pack functionality to be stepped through.
.NET Source Code Debugging
Unlike MFC, ATL, and the CRT, which have had the library source code available since the earliest days of Visual C++, the source code for the .NET Framework Libraries has not been available generally until now. An earlier effort to address the unavailability of the .NET Framework Library source code was the Shared Source CLI (Common Language Infrastructure) project, commonly referred to by its code-name of Rotor. Rotor, which is available in both a .NET 1.x and 2.0 version, is a stripped down version of the .NET runtime and Framework Libraries that contains a great deal of commonality with the commercial .NET releases. Unfortunately for Managed Extension and C++/CLI developers, the only compilers included with Rotor are a C# and JScript compiler.
To widen the audience and simplify the process of stepping into the .NET source code, Microsoft announced the release of the source code for the Framework Libraries in late 2007. The recently released Visual Studio 2008 SP1 makes stepping into the .NET source code extremely simple—a single setting on the Debugging | General options page configures all the required settings to allow Visual Studio to download the relevant debug symbol files and source code, as shown in Figure 5.
Figure 5: Visual Studio 2008 SP1 .NET Source Code Stepping
As of late August 2008, the debug symbol files for .NET Framework 3.5 SP1 were available, but the corresponding source code was not available. Visual Studio 2008 SP1 will attempt to download the source code file, but the error message shown in Figure 6 will be displayed in the Output Window.
Figure 6: Source Server Error Messages
For Visual Studio 2008 without SP1, the first step for Framework source code stepping is applying a Visual Studio 2008 QFE. After the QFE has been applied, Enable source Server support needs to be checked, as shown in Figure 5. The final step is to place an entry for the .NET Framework Source Symbol server (http://referencesource.microsoft.com/symbols) in the Debugging | Symbols settings before the setting for the standard Microsoft symbol server. The reason that the .NET Framework DLLs need a special symbol server is the same as the reason for the MFC and ATL debug symbols—the standard symbol server has debug symbol files with the source information stripped out. Figure 7 shows the final Debug Symbol settings.
Figure 7: Visual Studio Symbols for ATL/MFC and .NET Source Debugging
Once these settings have been set up correctly, it will be possible to step into .NET code in the same manner as ATL and MFC code. If the check-box Search the above locations only when symbols are loaded manually on the Symbols setting dialog is checked, Visual Studio will not load the .NET Framework symbols automatically, and the context menu of the Module debug window or the Call Stack debug window will need to be used to load the symbols manually. This will give a faster start to debug sessions, but the draw back is the need to go through each DLL manually and load the symbols when they are needed. If the Framework source code is being stepped into frequently, clearing the checkbox is recommended.
If all the settings have been applied correctly, stepping into the Framework source code is a simple matter of pressing F11 at the appropriate breakpoint. Figure 8 shows the results of successfully stepping into the Console class.
Figure 8: .NET Framework Source Code Stepping
There is no greater source of documentation than the actual source code of a function. By configuring Visual C++ to be able to step through the ATL, MFC, and .NET Framework libraries, it is possible to gain a much greater depth of understanding about problems that are occurring, and why certain libraries behave like they do. Although it is never safe to rely on undocumented behaviour or implementation specifics, the actual source code can provide a great supplement to the MSDN documentation, and significantly enhance developer productivity. With a little effort and attention to detail, setting up Visual C++ to be able to step into the source code of any of Microsoft's libraries is easily achievable.
About the Author
Nick Wienholt is an independent Windows and .NET consultant based in Sydney. He is the author of Maximizing .NET Performance and co-author of A Programmers Introduction to C# 2.0 from Apress, and specializes in system-level software architecture and development, with a particular focus of performance, security, interoperability, and debugging.
Nick is a keen and active participant in the .NET community. He is the co-founder of the Sydney Deep .NET User group and writes technical article for Australian Developer Journal, ZDNet, Pinnacle Publishing, Developer.COM, MSDN Magazine (Australia and New Zealand Edition) and the Microsoft Developer.