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

Configuration: ¡Release

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.

SugslayerUtil Property Pages

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.

0 0

Post a comment

  • Receive news updates via email from this site