Visual Studio: debug information in release build - visual-studio

I'm tempted to include debug information in my release builds that go out to customers. As far as I see the only down side is 25% increase in the binary file size. The advantage is that I can get an immediately usable crash dump, much easier to analyze.
I'm willing to live with the 25% increase. Are there any other disadvantages I'm missing?
This is a C project and all I want to do is Linked/Debugging/Generate Debug Info

The size of the executable should increase much less than 25%.
I'm actually a little surprised that it increases much at all, but some quick tests show that at least one large example project (ScummVM) increases the .exe from 10,205,184 bytes to 10,996,224 bytes just by adding the /DEBUG option to the link step (about an 8% increase). /DEBUG is specified using the "Linker | Debugging | Generate Debug Info" option in the IDE. Note that this settings should have no effect on the optimizations generated by the compiler.
I know that a pointer to the .pdb file is put in the executable, but there's not much to that. I experimented a bit and found that enabling the /OPT:REF linker option changed the size difference to 10,205,184 vs. 10,205,696. So the non /DEBUG build stayed the same size, but the /DEBUG build dropped to only 512 bytes larger (which could be accounted for by the pointer-to-.pdb - maybe the linker rounds to some multiple of 512 or something). Much less than 1% increase. Apparently, adding /DEBUG causes the linker to keep unreferenced objects unless you also specify /OPT:REF. ("Linker | Optimization | References" option in the IDE).
The program will run fine without the .pdb file - you can choose to send it to customers if you want to provide a better debugging experience at the customer site. If you just want to be able to get decent stack traces, you don't need to have the .pdb file on the customer machine - they (or some tool/functionality you provide) can send a dump file which can be loaded into a debugger at your site with the .pdb file available and get the same stack trace information port-mortem.
Of course, one thing to be aware of is that you'll need to archive the .pdb files along with your releases. The "Debugging Tools for Windows" package (which is now distributed in the Windows SDK) provides a symbol server tool so you can archive .pdb files and easily retrieve them for debugging.
The only drawback that I can think of to distributing .pdb files is that it can make reverse engineering your application easier, if that's a concern for you. Note that Microsoft distributes symbols for Windows (using a public symbol server - as well as packages of the full symbols sets for some specific releases). However, the symbols they distribute do get run through a sanitizing step that removes certain items they consider sensitive. You can do the same (or similar) using the linker's /PDBSTRIPPED option ("Linker | Debugging | Strip Private Symbols" in the IDE). See the MSDN documentation for details on what the option removes. If you're going to distribute symbols, it's probably appropriate to use that option.

According to the Visual Studio 2005 documentation at Visual Studio 2005 Retired documentation:
/DEBUG changes the defaults for the /OPT option from REF to NOREF and
from ICF to NOICF (so, you will need to explicitly specify /OPT:REF or
/OPT:ICF).
In my case it helped when I enabled both:
/O2 /DEBUG /OPT:REF /OPT:ICF

You don't mention what language you're in, and there might be different answers for C++ vs. C#.
I'm not 100% sure what change you're considering making. Are you going to tell Visual Studio to make its standard Debug compile, and ship that, or are you going to edit a couple settings in the Release compile? A careful modification of a couple of settings in the Release build strikes me as the best approach.
Whatever you end up with, I'd make sure that optimizations are turned on, as that can make a significant difference in the performance of the compiled code.

I always send out the debug build, never the release build. I can't think of any disadvantages, and the advantages are as you mention.

Related

How can Visual Studio automatically build and test C# code?

I'm used to Eclipse for Java projects which automatically builds whenever I save a file. (I can turn this off.)
I then install Infinitest which automatically runs all tests affected by the change saved.
Hows do I do this for Visual Studio, writing C# software?
Important note:
If you're only concerned about C#/.NET code and only want to run Unit Tests, then this feature already exists in Visual Studio 2017 (Enterprise edition only) called Live Unit Testing, read more about it here: https://learn.microsoft.com/en-us/visualstudio/test/live-unit-testing-intro?view=vs-2017
Live Unit Testing is a technology available in Visual Studio 2017 version 15.3 that executes your unit tests automatically in real time as you make code changes.
My original answer:
(I used to be an SDE at Microsoft working on Visual Studio (2012, 2013, and 2015). I didn't work on the build pipeline myself, but I hope I can provide some insight:)
How can Visual Studio automatically build and test code?
It doesn't, and in my opinion, it shouldn't, assuming by "build and test code" you mean it should perform a standard project build and then run the tests.
Eclipse only builds what is affected by the change. Works like a charm.
Even incremental builds aren't instant, especially if there's significant post-compile activity (e.g. complicated linking and optimizations (even in debug mode), external build tasks (e.g. embedding resources, executable compression, code signing, etc).
In Eclipse, specifically, this feature is not perfect. Eclipse is primarily a Java IDE and in Java projects it's quite possible to perform an incremental build very quickly because Java's build time is very fast anyway, and an incremental build is as simple as swapping an embedded .class file in a Java .jar. In Visual Studio, for comparison, a .NET assembly build time is also fast - but not as simple, as the output PE (.exe/.dll) file is not as simple to rebuild.
However in other project types, especially C++, build times are much longer so it's inappropriate to have this feature for C/C++ developers, in fact Eclipse's own documentation advises C/C++ users to turn this feature off:
https://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.cdt.doc.user%2Ftasks%2Fcdt_t_autobuild.htm
By default, the Eclipse workbench is configured to build projects automatically. However, for C/C++ development you should disable this option, otherwise your entire project will be rebuilt whenever, for example, you save a change to your makefile or source files. Click Project > Build Automatically and ensure there is no checkmark beside the Build Automatically menu item.
Other project types don't support this feature either, such as Eclipse's plugin for Go:
https://github.com/GoClipse/goclipse/releases/tag/v0.14.0
Changes in 0.14.0:
[...]
Project builder is no longer invoked when workspace "Build Automatically" setting is enabled and a file is saved. (this was considered a misfeature anyways)
(That parenthetical remark is in GoClipse's changelist and certainly makes clear that plugin's authors' opinions of Automatic Builds)
I then install Infinitest which automatically runs all tests affected by the change saved.
Visual Studio can run your tests after a build automatically (but you still need to trigger the build yourself), this is a built-in feature, see here:
https://learn.microsoft.com/en-us/visualstudio/test/run-unit-tests-with-test-explorer?view=vs-2017
To run your unit tests after each local build, choose Test on the standard menu, and then choose Run Tests After Build on the Test Explorer toolbar.
As for my reasons why Visual Studio does not support Build-on-Save:
Only the most trivial C#/VB and TypeScript projects build in under one second, the other project types, like C, C++, SQL Database, etc take between a few seconds for warm rebuilds of simple projects - to literally hours for large-scale C++ projects with lots of imported headers on a single-core CPU, low RAM and with a 5,400rpm IDE hard-drive.
Many builds are very IO-intensive (especially C/C++ projects with lots of headers *cough*like <windows.h>*cough*) rather than CPU-bound, and disk IO delays are a major cause of lockups and slowdowns in other applications running on the computer because a disk paging operation might be delayed or because they're performing disk IO operations on the GUI thread, and so on - so with this feature enabled in a disk IO-heavy build it just means your computer will jitter a lot every time you press Ctrl+S or whenever autosave runs.
Not every project type supports incremental builds, or can support a fast incremental build. Java is the exception to this rule because Java was designed so that each input source .java file maps 1-to-1 to an output .class file, this makes incremental builds very fast as only the actually modified file needs be rebuilt, but other projects like C# and C++ don't have this luxury: if you make even an inconsequential 1-character edit to a C preprocessor macro or C++ template you'll need to recompile everything else that used that template - and then the linker and optimizer (if code-inlining) will both have to re-run - not a quick task.
A build can involve deleting files on disk (such as cleaning your build output folder) or changing your global system state (such as writing to a non-project build log) - in my opinion if a program ever deletes anything under a directory that I personally own (e.g. C:\git\ or C:\Users\me\Documents\Visual Studio Projects) it had damn well better ask for direct permission from me to do so every time - especially if I want to do something with the last build output while I'm working on something. I don't want to have to copy the build output to a safe directory first. This is also why the "Clean Project" command is separate and not implied by "Build Project".
Users often press Ctrl+S habitually every few seconds (I'm one of those people) - I press Ctrl+S even when I've written incomplete code in my editor: things with syntax errors or perhaps even destructive code - I don't want that code built at all because it isn't ready to be built! Even if I have no errors in my code there's no way for the IDE to infer my intent.
Building a project is one way to get a list of errors with your codebase, but that hasn't been necessary for decades: IDEs have long had design-time errors and warnings without needing the compiler to run a build (thanks to things like Language Servers) - in fact running a build will just give me double error messages in the IDE's error window because I will already have error messages from the design-time error list.
Visual Studio, at least (I can't speak for Eclipse) enters a special kind of read-only mode during a build: so you can't save further changes to disk while a build is in progress, you can't change project or IDE settings, and so on - this is because a the build process is a long process that depends on the project source being in a fixed, known state - the compiler can't do its job if the source files are being modified while it's reading them! So if the IDE was always building (even if just for a few seconds) after each save, users won't like how the IDE is blocking them from certain editing tasks until the build is done (remember IDEs do more than just show editors: some specialized tool window might need to write to a project file just to open).
Finally, Building is not free of side-effects (in fact, that's the whole point!) - there is always a risk something could go wrong in the build process and break something else on your system. I'm not saying building is risky, but if you have a custom build script that does something risky (e.g. it runs a TRUNCATE TABLE CriticalSystemParameters) and the build breaks (because they always do) it might leave your system in a bad state.
Also, there's the (slightly philosophical) problem of: "What happens if you save incomplete changes to the build script of your project?".
Now I admit that some project types do build very, very quickly like TypeScript, Java and C#, and others have source-files that don't need compiling and linking at all and just run validation tools (like PHP or JavaScript) - and having Build-on-Save might be useful for those people - but arguably for the limited number of people whose experience it improves it demonstrably worsens it for the rest of the users.
And if you really want build-on-save, it's trivial enough to write as an extension for Visual Studio (hook the "File Save" command and then invoke the Project Build command in your handler) - or get into the habit of pressing Ctrl+B after Ctrl+S :)
VS 2017 Enterprise Edition supports a Live Unit Testing feature. For older versions, or lower editions, some third party providers such as Mighty Moose or NCrunch are available (other third party solutions almost certainly exist also)

What is the difference between .ilk and .iobj files?

I noticed that Visual Studio generates *.ilk files for debug builds and *.iobj files for release builds. As I understand, both of these file types are used as input for incremental linker. What is the difference between them? Can they be used together? How can I disable these files in project settings?
According to this answer, .iobj files are produced to support incremental link-time code generation (aka LTCG, and what used to be called, I believe, 'whole program optimization') and LTCG is normally only enabled for release builds.
One optimisation that LTCG can perform is inline a function from another compilation unit (i.e. source file). The compiler (of course) can't do this. There are no doubt others.
.ilk files, on the other hand, support incremental linking for debug builds, to get fast link times. This is not the same as incremental LTCG, where the linker tries to make use of cross-compilation-unit optimisations that it has done before, again to speed things up, but in a different way.
It follows that to suppress generation of .iobj files, turn off 'incremental link time code generation' for your project, and to suppress generation of .ilk files, turn off 'incremental linking'. I believe that both of these are linker options. But why bother? - they speed up development. Instead, I delete these files when I archive [a version of] my project.
Incremental linking is normally turned off for release builds, although I'm not sure why. Perhaps the two options are mutually incompatible, I've never tried enabling them both at once. Or maybe MS figured that we were fed up with them cluttering up our hard disks with build products, who knows?

In MSVS what are symbols and why it is required to be cached?

In MSVS 2010 if you go to Tools->Options->Debuggibg, the following window opens.
I want to know what are these symbols? And why we want to cache it ? Is it too big for 500 GB drives which are common now a days?
Symbols are the .pdb files that are generated when you build your code with the proper features enabled. These files provide a mapping from the binary code to the actual statement that was written for that piece of binary to be generated.
Since they're usually downloaded from a remote location and since they don't change that often for external libraries, it really speeds up the debugging when you don't have to download these files each and every time.
On my machine the symbol cache is about 600MB in size. Your 500GB drive should be more than enough for normal operations.
See also: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363368(v=vs.85).aspx
This feature is especially powerful when you have Framework Source Stepping enabled, this, in combination with the Microsoft Symbol Server, allows you to debug certain parts of the .NET framework. The symbols are downloaded from Microsoft and from the symbols Visual Studio reads which source file(s) to download to enable debugging for you.
The Symbol cache is used during debugging, to give richer information. There is a similar dialog inside each solution that defines what level of debug symbols are generated during the building of your solution. This is where the Assembler/Compiler is told what to do with these things.
And inside Team Build (if you're running TFS) there is an option to generate these symbol files during the automated build process. These files can then be referenced from IntelliTrace or WinDbg to provide you a richer debugging experience without having to deploy a debug version or the debug symbols to your production environment (deploying the .pdb files to you production environment causes higher memory usage and a small performance hit because the runtime will load these symbols into memory. When exceptions happen it will also cause additional overhead, because these are enriched with the information found in the symbol files.
See: http://msdn.microsoft.com/en-us/library/vstudio/hh190722.aspx

Any recommended VC++ settings for better PDB analysis on release builds

Are there any VC++ settings I should know about to generate better PDB files that contain more information?
I have a crash dump analysis system in place based on the project crashrpt.
Also, my production build server has the source code installed on the D:\, but my development machine has the source code on the C:\. I entered the source path in the VC++ settings, but when looking through the call stack of a crash, it doesn't automatically jump to my source code. I believe if I had my dev machine's source code on the D:\ it would work.
"Are there any VC++ settings I should know about"
Make sure you turn off Frame pointer ommision. Larry osterman's blog has the historical details about fpo and the issues it causes with debugging.
Symbols are loaded successfully. It shows the callstack, but double clicking on an entry doesn't bring me to the source code.
What version of VS are you using? (Or are you using Windbg?) ... in VS it should defintely prompt for source the first time if it doesn't find the location. However it also keeps a list of source that was 'not found' so it doesn't ask you for it every time. Sometimes the don't look list is a pain ... to get the prompt back up you need to go to solution explorer/solution node/properties/debug properties and edit the file list in the lower pane.
Finally you might be using 'stripped symbols'. These are pdb files generated to provide debug info for walking the callstack past FPO, but with source locations stripped out (along with other data). The public symbols for windows OS components are stripped pdbs. For your own code these simply cause pain and are not worth it unless you are providing your pdbs to externals. How would you have one of these horrible stripped pdbs? You might have them if you use "binplace" with the -a command.
Good luck! A proper mini dump story is a godsend for production debugging.
If your build directly from your sourcecode management system, you should annotate your pdb files with the file origins. This allows you to automatically fetch the exact source files while debugging. (This is the same proces as used for retrieving the .Net framework sourcecode).
See http://msdn.microsoft.com/en-us/magazine/cc163563.aspx for more information. If you use subversion as your SCM you can check out the SourceServerSharp project.
You could trying using the MS-DOS subst command to assign your source code directory to the D: drive.
This is the procedure I used after some trouble similar to yours:
a) Copied to the production server all the EXE & DLL files that were built, each with its corresponding PDB to the same directory, started the system, and waited for the crash to happen.
b) Copied back all the EXE, DLL & PDB files to the development machine (to a temporary folder) along with the minidump (in the same folder). Used Visual Studio to load the minidump from that folder.
Since VS found the source files where they were originally compiled, it was always able to identify them and load them correctly. As with you, in the production machine the drive used was not C:, but in the development machine it was.
Two more tips:
One thing I did often was to copy an EXE/DLL rebuilt and forget to copy the new PDB. This ruined the debug cycle, VS would not be able to show me the call stack.
Sometimes, I got a call stack that didn't make sense in VS. After some headache, I discovered that windbg would always show me the correct stack, but VS often wouldn't. Don't know why.
In case anyone is interested, a co-worker replied to this question to me via email:
Artem wrote:
There is a flag to MiniDumpWriteDump()
that can do better crash dumps that
will allow seeing full program state,
with all global variables, etc. As for
call stacks, I doubt they can be
better because of optimizations...
unless you turn (maybe some)
optimizations off.
Also, I think disabling inline
functions and whole program
optimization will help quite a lot.
In fact, there are many dump types,
maybe you could choose one small
enough but still having more info
http://msdn.microsoft.com/en-us/library/ms680519(VS.85).aspx
Those types won't help with call stack
though, they only affect the amount of
variables you'll be able to see.
I noticed some of those dump types
aren't supported in dbghelp.dll
version 5.1 that we use. We could
update it to the newest, 6.9 version
though, I've just checked the EULA for
MS Debugging Tools -- the newest
dbghelp.dll is still ok to
redistribute.
Is Visual Studio prompting you for the path to the source file? If it isn't then it doesn't think it has symbols for the callstack. Setting the source path should work without having to map the exact original location.
You can tell if symbols are loaded by looking at the 'modules' window in Visual Studio.
Assuming you are building a PDB then I don't think there are any options that control the amount of information in the PDB directly. You can change the type of optimizations performed by the compiler to improve debuggabilty, but this will cost performance -- as your co-worker points out, disabling inline will help make things more obvious in the crash file, but will cost at runtime.
Depending on the nature of your application I would recommend working with full dump files if you can, they are bigger, but give you all the information about the process ... and how often does it crash anyway :)
Is Visual Studio prompting you for the
path to the source file?
No.
If it isn't then it doesn't think it has symbols
for the callstack. Setting the source
path should work without having to map
the exact original location.
Symbols are loaded successfully. It shows the callstack, but double clicking on an entry doesn't bring me to the source code. I can of course search in files for the line in question, but this is hard work :)

Attaching to a foreign executable in Visual C++ 2003

I have an executable (compiled by someone else) that is hitting an assertion near my code. I work on the code in Visual C++ 2003, but I don't have a project file for this particular executable (the code is used to build many different tools). Is it possible to launch the binary in Visual C++'s debugger and just tell it where the sources are? I've done this before in GDB, so I know it ought to be possible.
Without the PDB symbols for that application you're going to have a tough time making heads or tails of what is going on and where. I think any source code information is going to be only in that PDB file that was created when whoever built that application.
This is assuming that the PDB file was EVER created for this application - which is not the default configuration for release mode VC++ projects I think. Since you're asserting, I guessing this is a debug configuration?
Short of any other answers, I would try attaching to the executable process in Visual Studio, setting a break point in your code and when you step into the process you don't have source to, it should ask for a source file.
Yes, it's possible. Just set up an empty project and specify the desired .exe file as debug target. I don't remember exactly how, but I know it's doable, because I used to set winamp.exe as debug target when I developed plug-ins for Winamp.
Since you don't have the source file it will only show the assembly code, but that might still be useful as you can also inspect memory, registers, etc.
Update
If you are debugging an assertion in your own program you should be able to see the source just fine, since the path to the source file is stored in the executable when you compile it with debug information.

Resources