What’s Z7 and Zi?
These are compiler switches which tells the compiler where to dump debugging information collected from a C/C++ source file during compilation. Z7 tells the compiler to dump debugging information into a .obj file. Zi tells the compiler to dumps debugging information into an intermediate .pdb file.
What’s the Difference between Z7 and Zi?
This option produces a .obj file containing full symbolic debugging information for every C/C++ source compiled for use with the linker. The symbolic debugging information includes the names and types of variables, as well as functions and line numbers. .Obj files get bigger in size because of the debugging information dumped in by the compiler into this file and then bloats your disk. /Z7 is based on the old code view format. This option introduces additional burden on the linker to parse every .obj file for debugging information. These .obj files will then be collated into a one .pdb file which will normally be named after the executable file name during linking phase.
Advantages of using Z7 switch
- Good thing here is that there is no contention to write to one file (as you’ll see below).
- Every .cpp file will have its own debugging information which will eventually be collated by the linker.
Disadvantages of using Z7 switch
- Downside being the time taken to link, size of files on disk and old format.
- Minimal rebuild feature (/Gm) will not work if /Z7 is enabled. You’ll get following warning…
Command line warning D9007: ‘/Gm’ requires ‘/Zi or /ZI’; option ignored
- The biggest disadvantage of Z7 is that this format doesn’t allow Edit and Continue, well this matters if you use this feature at all?
During Debugging what’s the effect of Z7 switch?
When debugging the debugger will tell us from where it has loaded a pdb file for a binary that its debugging. It loads the pdb file generated by the Linker which is unaffected by either /Zi or /Z7. Please see highlighted path of .pdb file from the debugger. So yes linker generates .pdb file which is the final .pdb file.
ConsoleApplication4.exe .\ConsoleApplication4.exe Symbols loaded. .\ConsoleApplication4.pdb 00E50000-00E70000  ConsoleApplication4.exe: Native
With /Z7 enabled you’ll see following list of files in your intermediate folder, note the size of .obj files…
10/23/2014 06:07 PM 136 ConsoleApplication4.res 10/23/2014 06:07 PM 348 ConsoleApplication4.log 10/23/2014 06:07 PM 2,473 ConsoleApplication4.Build.CppClean.log 10/23/2014 06:07 PM 117,615 ConsoleApplication4.obj 10/23/2014 06:07 PM 4,920,987 stdafx.obj 10/23/2014 06:07 PM 36,175,872 ConsoleApplication4.pch
Please compare above size of .obj files with below output files generated when /Zi is enabled.
The compiler writes debugging information to one centralized file. The compiler names the program database named VCx0.pdb (or what you’ve configured it to be named), where x is the major version of Visual C++ in use.
Advantages of using Zi
- When you use this option, your .obj files will be smaller, because debugging information is stored in the .pdb file rather than in .obj files.
- Easy on the linker. It just has one file to parse to figure out debugging information for a binary that’s linking up.
- Duplicate debugging information doesn’t make into the .pdb file generated by the compiler since its now working on one .pdb file instead of multiple .obj files where it doesn’t maintain a list of symbols generated to figure out duplicate ones.
- Minimal Rebuild (/Gm) will work only work with /Zi or /ZI.
- Advanced debugging features like Edit and Continue (/ZI) will work (making code changes when debugging, the changes are then built and we continue debugging again without stopping the debugging session). Sample effect on the debugger when a code change is done when debugging with Edit and Continue enabled…
——– Edit and Continue build started ——–
——————— Done ———————-
Disadvantages of using Zi
- High contention to write to the one .pdb file as we’ve parallel builds running. Some machines will have several parallel builds configured.
With Zi enabled you’ll see following list of files generated. Take a note of sizes for the .obj files. Note that now we’ve got a
10/23/2014 06:00 PM 136 ConsoleApplication4.res 10/23/2014 06:00 PM 192 ConsoleApplication4.log 10/23/2014 06:00 PM 2,473 ConsoleApplication4.Build.CppClean.log 10/23/2014 06:00 PM 103,106 ConsoleApplication4.obj 10/23/2014 06:00 PM 933,490 stdafx.obj 10/23/2014 06:00 PM 1,551,360 vc120.idb 10/23/2014 06:00 PM 4,239,360 vc120.pdb <<<-- This is the pdb that the compiler generates, which contains debugging information from all the cpp files (path is generated using following pattern: $(IntDir)vc$(PlatformToolsetVersion).pdb). Now .obj files will not have debugging information. Compare their sizes with earlier output. 10/23/2014 06:00 PM 36,896,768 ConsoleApplication4.pch
When debugging the debugger tells exactly from where a pdb file is loaded. It loads the pdb file generated by the Linker which is unaffected by either /Zi or /Z7. Please see highlighted path of .pdb file from the debugger. So yes linker generates .pdb file which is the final .pdb file.
ConsoleApplication4.exe .\ConsoleApplication4.exe Symbols loaded. .\ConsoleApplication4.pdb  ConsoleApplication4.exe: Native
What’s the effect of these options when debugging in Visual Studio or a crash dump?
As far as debugging is concerned there is zero effect as the linker will eventually generate one final pdb file which is controlled by the linker switch: /DEBUG.
The compiler only generates an ‘intermediate’ .pdb file which contains debugging information collected during compilation which the linker will then eventually dump to a ‘final’ .pdb file. So all that you should be worried is the final .pdb file generated by the linker. This .pdb file is placed alongside the executable. This is the .pdb file that will be used when debugging the application or crash dumps.
So you might ask what if we disable .pdb generation in the compiler settings? Well then your code breakpoints will not hit. The breakpoints will be disabled since the linker couldn’t figure symbols for your code as the compiler didn’t generate any!
Please let me know if you have further questions?