Build All Builds with Debugging Symbols
Some of the debugging system recommendations that I do make aren't that controversial. I've been harping on my first recommendation for years: build all builds, including release builds, with full debugging symbols. Debugging symbols are the data that let the debugger show you source and line information, variable names, and data type information for your program. All that information is stored in a .PDB (Program Database) file associated with your modules. If you're paid by the hour, spending forever at the assembly language level could do wonders for paying your mortgage. Unfortunately, the rest of us don't have the luxury of infinite time, so speedily finding those bugs is a priority.
Of course, debugging release builds with symbols has its drawbacks. For example, the optimized code that the just-in-time (JIT) compiler or native compiler produces won't always match the flow of execution in the source code, so you might find that stepping through release code is a little harder than stepping through debug code. Another problem to watch out for in native release builds is that sometimes the compiler optimizes the stack registers such that you can't see the complete call stack, as you would in a straight debug build. Also be aware that when you do add debugging symbols to the binary, it will grow a small amount to account for the debug section string that identifies the .PDB file. However, the few-byte size increase is negligible when compared to the ease of being able to solve bugs quickly.
Turning on debug symbols for a release build is quite easy, though it should have been turned on by default in the wizard-generated projects. For a C# project, open the project Property Pages dialog box and select the Configuration Properties folder. Select All Configurations or Release in the Configurations dropdown list, display the Configuration Properties folder, Build property page, and set the Generate Debugging Information field to True. This sets the /debug:full flag for CSC.EXE. Figure 2-1 shows the project Property Pages dialog box in which you turn on debugging information.
3uqslityerUtil.NET Property Pages
Configuration:
Active(Release)
Cj Common Properties .J Configuration Properties ir Build Debugging Advanced
Active(.NET)
Configuration Manager.
Active(.NET)
|
] Code GeiteiMiart | ||
|
Conditional Compilation Constant TRACE | ||
|
Optimize Code |
True | |
|
Check for Arithmetic Overflow/Ur False | ||
|
Allow Unsafe Code Blocks |
False | |
|
- ] Errors .nd We nings | ||
|
Warning Level |
Warning level 4 | |
|
Treat Warnings As Errors |
True | |
|
Suppress Specific Warnings | ||
|
] Outputs | ||
|
Output Path |
. ,\Release\ | |
|
XML Documentation File |
BugslayerUtil.NET. XML | |
|
Generate Debugging Information |
True T | |
|
Register for COM Inteiop |
False | |
|
Generate Debugging Information | ||
|
Generate debugging information and place it in the output file(s) (/debug). | ||
Cancel
Help
Figure 2-1: Generating debugging information for a C# project
For reasons that I still can't quite fathom, the Microsoft Visual Basic .NET project Property Pages dialog box is different from the one for C# projects, but the compiler switch is still the same. Figure 2-2 shows setting a release build that produces full debug symbols. Open the project Property Pages dialog box and select the Configuration Properties folder. Select All Configurations or Release in the Configuration drop down list, display the Configuration Properties folder, Build property page, and check the Generate Debugging Information check box.
- Figure 2-2: Generating debugging information for a Visual Basic .NET project
For native C++, the /Zi switch turns on the PDB file for the compiler. In the project Property Pages dialog box, display the C/C++ folder, General property page, and set Debug Information Format to Program Database (/Zi). Make sure you don't select Program Database For Edit & Continue or your release build will be built with all the extra padding bytes necessary for editing and continuing, and thus be quite fat and slow. Figure 2-3 shows the appropriate compiler settings. There are other settings for better builds set in Figure 2-3, and I'll discuss them in the Common Debugging Question, "What additional compiler and linker options will help me with my proactive debugging of native code?"
SugslayerUtil Property Pages
|
Q Configuration Propertie: |
a |
|
General | |
|
Debugging | |
|
â C/C++ | |
|
¡^ General | |
|
Optimization | |
|
Preprocessor | |
|
Code Generatio | |
|
Language | |
|
Precompiled He< | |
|
Output Files | |
|
Browse Informa | |
|
Advanced | |
|
Command Line | |
|
lLJ Linker | |
|
CJ Resources | |
|
CJ Browse Information | |
|
CJ Build Events | |
|
CJ Custom Build Step " | |
|
<1 | |
Platform: |Active(Win32)
Configuration Manager..
Additional Include Directories
Resolve #using References
Additional Include Directories
Resolve #using References
|
Debug Information Format |
Program Database (/Zi) | |
|
Suppress Startup Banner |
Yes (/no!ogo) | |
|
Warning Level |
level 4 (/W4) | |
|
Detect 64-bit Portability Issues |
Yes (/Wp64) | |
|
Treat Warnings As Errors |
Yes (/WX) |
Debug Information Format
Specifies the type of debugging information generated by the compiler. You must also change linker settings appropriately to match. (/Z7, Zd, jZ\, /ZI)
Cancel
Help
Figure 2-3: Setting the C++ compiler to generate debugging information
After setting the compiler switch, you'll need to set the appropriate linker switches: /incremental:no, /debug, and /pdb. The incremental linking option resides in the project Property Pages dialog box, Linker folder, General property page, and Enable Incremental Linking field. Figure 2-4 shows the switch location.
SugslayerUtil Property Pages
Configuration: ¡Release
.J Configuration Properties General Debugging CJ C/C++ Linker ¡^ General Input Debugging System Optimization EmbeddedIDL Advanced Command Line Resources Cj Browse Information lj Build Events Pi Custom Build Step : 3 Web Deployment
Platform: |Active(Win32)
Configuration Manager..
Output File
$(OutDir)/$(ProjectName).dll
Platform: |Active(Win32)
Configuration Manager..
Output File
$(OutDir)/$(ProjectName).dll
|
Show Progress |
Not Set | |
|
Version | ||
|
Enable Incremental Linkjng |
1 Njji (/INCREMENTAI.:NO) |
T |
|
Suppress Startup Banner |
Ves (/NULOGO) | |
|
ignore Import Library |
No | |
|
Register Output |
Wt| | |
|
Additional Library Directories |
¿(OiitDir) | |
Enable Incremental Linking
Enables incremental linking. (/INCREMENTAL., /INCREMENTAL:NO)
Cancel
Help
Figure 2-4: Turning off incremental linking in the C++ linker
In the project Property Pages dialog box, Linker folder, Debugging property page, set the Generate Debug Info option to Yes (/DEBUG). To set the /pdb option, place $(OutDir)/$(ProjectName).PDB in the Generate Program Database File option, which is directly below the Generate Debug Info field. In case you haven't noticed, the Microsoft Visual Studio .NET project system finally fixed some of the big problems prior versions had with generic build options. The values starting with $ and in parentheses are macro values. From their names, you can probably guess what they are. All the other macros are accessible by clicking in most editable options in the property page and then selecting <Edit...> from the drop-down list. The dialog box that pops up will show all the macros and what they'll expand to. Figure 2-5 demonstrates how to set the /debug and /pdb switches. The rest of the settings in the figure are important for native C++ code. Later in the chapter, I'll discuss the Common Debugging Question, "What additional compiler and linker options will help me with my proactive debugging of native code?"
SugslayerUtil Property Pages
Configuration: ¡Release
.J Configuration Properties General Debugging CJ C/C++ Linker General Input ¡^ Debugging System Optimization EmbeddedIDL Advanced Command Line Resources Cj Browse Information lj Build Events Pi Custom Build 5tep : 3 Web Deployment
Platform: |Active(Win32)
Configuration Manager..
Platform: |Active(Win32)
Configuration Manager..
|
Generate Debua Info |
Yes(/DEBUG) t | |
|
Generate Program Database File |
$(OutDir)/$(ProjectName).pdb | |
|
Strip Private Symbols |
$(OutDir)/i(ProjectName)_STRIPPED.pdb | |
|
Generate Map File |
Yes (/MAP) | |
|
Map File Name |
$(OutDir)/$(ProjectName).map | |
|
Map Exports |
Yes (/MAPINFO:EXPORTS) | |
|
Map Lines |
Yes (/MAPINFO:LINES) | |
|
Debuggable Assembly |
No Debuggable attribute emitted | |
|
Generate Debug Info | ||
|
Enables generation of debug information. (/DEBUG) | ||
Cancel
Help
Cancel
Help
Figure 2-5: C++ linker debug node settings
To properly get debugging symbols for C++, two more settings are necessary: /opt:REF and /opt:ICF. Both switches are set in the Linker folder, Optimization property page, as shown in Figure 2-6. Set the References option to Eliminate Unreferenced Data (/OPT:REF). Set the Enable COMDAT Folding option to Remove Redundant COMDATs (/OPT:ICF). Using the /debug switch with the linker automatically tells the switch to bring in all functions whether or not they are referenced, which is the default for debug builds. The /opt:REF switch tells the linker to bring in only functions that your program calls directly. If you forget to add the /opt:REF switch, your release application will also contain the functions that are never called, making the application much larger than it should be. The /opt:ICF switch will combine identical data COMDAT records when necessary so that you'll have only one constant data variable for all references to that constant value.
|
Configuration: | Release |
I Platform: |Active(Win32) |
Configuration Manager... | |
|
Configuration Properties |
Eliminate Unreferenced Data (/OPT:REF) t | ||
|
General |
Enable COMDAT Folding Remove Redundant COMDATs (/OPT:ICF) | ||
|
Debugging |
Optimize for Windows98 (/OPT:NOWIN98) | ||
|
D C/C++ |
Function Order | ||
|
■ jJ Linker | |||
|
General | |||
|
Input | |||
|
Debugging | |||
|
System | |||
|
¡^ Optimization | |||
|
EmbeddedIDL | |||
|
Advanced | |||
|
Command Line | |||
|
Resources | |||
|
Cj Browse Information | |||
|
Cj Build Events CJ Custom Build 5tep CJ Web Deployment | |||
|
Enables elimination of functions and/or data that are never referenced. | |||
|
(/OPT:REFj /OPT:NCREF) |
Help Cancel Help Figure 2-6: C++ optimization linker settings After you build your release builds with full PDB files, you need to store the PDB files in a safe place along with any binary files you ship to customers. If you lose your PDB files, you'll be right back to debugging at the assembly-language level. Treat your PDB files as you would your distributed binaries. If the thought of manually changing your project's settings to build with debug symbols, as well as the rest of the proper build switches, has you dreading the work, don't worry— there's hope. For Chapter 9, I wrote an extremely cool add-in, SettingsMaster, that takes all the work out of changing project settings. SettingsMaster's defaults are to set up your projects using the settings recommended in this chapter. | ||
Post a comment