Why not always build a release with debug info? - c++

If debug information is stored in a program database (not as part of an executable), is there any reason not to always build with it (e.g., MSVC's /Zi)?
In CMake, the default configurations are, "Release", "Debug", "RelWithDebInfo", and "MinSizeRel". Is there a reason not to only use "Debug" and "RelWithDebInfo" (perhaps renamed to "Release")?
Does it have any impacts on the size or performance of the code? Is the answer different for gcc or clang than it is for Visual C++?
Update
I did come across these posts that are similar:
Anything wrong with releasing software in debug mode?
Debug vs. RelWithDebInfo
However, neither of these get to the question of Release vs. RelWithDebInfo.
Yes. I could do a test on an executable with Release vs. RelWithDebInfo. That would definitely give me the answer about the size of the code, but would be very difficult to conclude that it has NO impact on performance if my test case showed similar performance. How would I know if I exercised aspects of the language that might be impacted by the change? That is, empirical testing could produce a false negative.

Releasing with debug info is mandatory for real-life development. When shit happens your primary tool would be a crash dump analysis that would be rather pointless without debug information. Note that this does not imply shipping debug info with product.
As for "little differences" between vc++ and gcc I would like to mention that by default vc++ emits debug information in a separate file while gcc will squeeze it into executable. It is possible to separate debug information on gcc as well, however doing so is not as convenient and requires some extra steps.

If you build as Release, surely you won't have Debug Info in the binary. I could see a lot of cases on Windows that people build "Release", but add flags to have debug info. So, i think the default real-life case for most Windows Users, even without knowing that, is Release With Debug Info.
With CMake, you have all three options and one more.
Release means no debugging symbols at all, and MAY also means build with optimizations.
RelWithDebugInfo means build with debug symbols, with or without optimizations. Anyway, the debug symbols can be stripped later, both using strip and/or obj-copy. If you use strip, the output can be saved. I guess the format is DWARF, version 4 or 5.
So, RelWithDebugInfo gives you Release mode binaries, and symbols can be stripped and kept apart. In some projects i have worked, that was the ONLY configuration used.
We must not forget about ASSERTS, at least for C/C++. Building with DEBUG, all Asserts are enabled, so they are not removed from the code during preprocessing. Release and RelwithDebugInfo remove the Asserts, so you won't have them. Some projects nowadays prefer to keep Asserts while developing (so that tests can catch "software" errors during development), and then finally remove in Production Code. Some other projects, for whom Fault-Tolerance is a must, may want to keep Asserts even in production code, so that software cannot execute with wrong Assertions about the software itself.
So,
RelWithDebugInfo: Optimized Build, With Symbols to be stripped, no Asserts
Debug: Not optimized, With Symbols that CAN be stripped, With Asserts.
Release: Optimized, No Symbols, No Asserts.

Recently we have cases on Release vs RelWithDebInfo, we compile a shared lib, and found either the performance and the lib file size has a significant difference, Release is much more runtime faster and less file size.
So it looks like Release should be used when shipping on production.

Related

Is there any reason why not to strip symbols from executable?

A couple of years ago I asked a question how to reduce size of executables. Using MinGW compiler, stripping symbols (-s option) helped to reduce 50%+ of the size.
Why the stripping is not default - is there any good reason why NOT to strip the symbols in some scenarios then? I'd like to understand it more deeply: today, I just vaguely know that symbols are involved in linking library. Are they needed in executable and do they affect executing speed?
I can't imagine them affecting the execution speed in any noticeable way though, in theory, you could have a tiny amount of cache misses in the process image.
You want to keep symbols in the file when you're debugging it, so that you can see which function you're in, check the values of variables and so forth.
But symbols make the file bigger: potentially, a lot bigger. So, you do not want symbols in a binary that you put on a small embedded device. (I'm talking about a real embedded device, not some 21st century Raspberry Pi with 9,000GB of storage space!)
I generally strip all release builds and don't strip any debug builds. This makes core dumps from customers slightly less useful, but you can always keep a copy of the unstripped release build and debug your core against that.
I did hear about one firm that had a policy of never stripping symbols even in release builds, so they could load a core directly into the debugger. This seems like a bit of an abstraction leak to me but, whatever. Their call.
Of course, if you really want, you can analyse the assembly yourself without them. But that's crazy...
MinGW is an acronym for "Minimalist GNU for Windows"; as such, the compiler suite is GCC ... the GNU Compiler Collection. Naturally, this compiler suite will tend to comply with the GNU Coding Standards, which demand that every build shall be a "debug build" ... i.e. it shall include both debugging symbols, and those required for linking. (This is logical, since a "debug build" is orders of magnitude more useful to the application developer, than is a so-called "release build"). Furthermore, a build system which discriminates between "debug build" and "release build" modes is more complex -- possibly significantly more so -- than one which concerns itself with only a "debug build".
In the GNU build model, there is no need for a "release build" anyway. A "release" is not created at build time; it is created at installation time -- usually as a "staged" installation, from which a release package is created. The GNU tool-chain includes both a strip command, and an install command, which can strip a "debug build" on the fly, when creating a staged installation for packaging as a release, (or in place, if you wish), so there really is no need to clutter the build system with "release build" specifics; just create a "debug build" up -front, then strip it after the event, so converting this to an effective "release build", when you require it.
Since your MinGW tool-chain is fundamentally a GNU tool-chain, it fully supports this GNU build model.
There is no good reason to strip symbols. By stripping symbols, for instance, you will eliminate a possibility to gather process stack - an extremely usuful feature.
EDIT. Several people here seem to be confused about the difference between debug symbols and 'general' symbols. The first are only produced when -g (or similar) option is given to the compiler, and are usually used only in debug builds (though can be used with optimized builds as well). The regular symbols are things such as function names, and are produced by compilers so that object files could be linked, or .so files loaded. There are several extremely useful non-invasive tools which can be used on non-debug running executables which depend on symbols being non-stripped.

I have a release binary with no debug information build with gcc , have source code

When I try to build the source with debug mode the stack shown is totally diffrent and in case of release there are only a few methods shown in the backtrace with gdb ,
Why does this happen ? Is this because in debug mode there are extra methods , How can have two methods have the same address in debug and release mode .
Also in that case How can I build to to have accurate address information with complete stack trace . Any help would be appreciated since I am new to debugging on Linux , Windows it was much easier it seems with pdb files .
As discussed in the comments to #rockoder's answer, besides lacking debug symbols (which would be included with -g) in an optimized build whole function calls may not be present any more due to inlining.
When I try to build the source with debug mode the stack shown is
totally diffrent and in case of release there are only a few methods
shown in the backtrace with gdb , Why does this happen ? Is this
because in debug mode there are extra methods?
It is probably just due to compiler optimizations. What you call release build is probably built with compiler speed optimizations enabled and debug symbols disabled. Speed optimizations include code inlining which just copies function code in place instead of calling it, so function is not visible in call stack.
There could also be some extra/different methods, if the code was written with some appropriate preprocessor checks.
How can have two methods have the same address in debug and release
mode .
Depends on what your debug and release mode are. If they use same compiler optimizations and differ only in debug information, methods will have same addresses. If you debug build is not optimized (-O0 on GCC) then methods will be larger, as much unnecessary work is done, for example variables are read from memory before every manipulation and written back after it. Since each method will probably be smaller, functions will have different addresses, as they are generally packed one after another.
Also in that case How can I build to to have accurate address
information with complete stack trace .
Enable debug information. On GCC that would be -g3 (or -g or similar). This adds enough information for code address <-> source line queries (either from debugger or crash stack dump).
Any help would be appreciated since I am new to debugging on Linux ,
Windows it was much easier it seems with pdb files .
Are there any significant differences with Windows binaries debugging?
g++/gcc has many options used for debugging a program but the most common one is -g. Refer link. The first option discussed is -g.
Some additional information here.
Example:
Compile code without -g:
g++ broken.cpp -o broken_release
Compile code with -g:
g++ -g broken.cpp -o broken_debug
Now fire ls -l and note the size different between the files broken_release and broken_debug. Size of broken_debug should be greater then that of broken_release. That's because it contains debug information which could be used by debuggers like gdb.

what does mean by debug build and release build, difference and uses [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Debug/Release difference
I want to know what do these two mean: Debug build and Release build and what is the difference between both.
Which one should I use (I mean which are the suitable conditions for each one)
and which build actually I am using now if I make a simple C++ project in Visual studio. [If I do not change any projects settings]
I am asking this because I am trying to make a GUI using wxWidgets 2.9.4 and they give different case of adding required .lib. these are
release ANSI static
debug ANSI static
release Unicode static
debug Unicode static
Please put a detailed answer.
Debug build and release build are just names. They don't mean anything.
Depending on your application, you may build it in one, two or more
different ways, using different combinations of compiler and linker
options. Most applications should only be build in a single version:
you test and debug exactly the same program that the clients use. In
some cases, it may be more practical to use two different builds:
overall, client code needs optimization, for performance reasons, but
you don't want optimization when debugging. And then there are cases
where full debugging (i.e. iterator validation, etc.) may result in code
that is too slow even for algorithm debugging, so you'll have a build
with full debugging checks, one with no optimization, but no iterator
debugging, and one with optimization.
Anytime you start on an application, you have to decide what options you
need, and create the corresponding builds. You can call them whatever
you want.
With regards to external libraries (like wxwidgets): all compilers have
some incompatibilities when different options are used. So people who
deliver libraries (other than in source form) have to provide several
different versions, depending on a number of issues:
release vs. debug: the release version will have been compiled with a
set of more or less standard optimization options (and no iterator
debugging); the debug version without optimization, and with iterator
debugging. Whether iterator debugging is present or not is one thing
which typically breaks binary compatibility. The library vendor should
document which options are compatible with each version.
ANSI vs. Unicode: this probably means narrow char vs wide wchar_t
for character data. Use which ever one corresponds to what you use in
your application. (Note that the difference between these two is much
more than just some compiler switches. You often need radically
different code, and handling Unicode correctly in all cases is far from
trivial; an application which truly supports Unicode must be aware of
things like composing characters or bidirectional writing.)
static vs. dynamic: this determines how the library is linked and
loaded. Usually, you'll want static, at least if you count on deploying
your application on other machines than the one you develop it on. But
this also depends on licensing issues: if you need a license for each
machine where the library is deployed, it might make more sense to use
dynamic.
When doing a DEBUG build the project is set up to not optimize (or only very lightly optimize) the generated code, and to tell the compiler to add debug information (which includes information about functions, variables, and other information needed for debugging). The pre-processor is set up to define the _DEBUG macro.
A RELEASE build on the other hand have higher level of optimization, and no debug information is saved. The pre-processor is set up to define the NDEBUG macro.
Another difference is that certain "system" macros, for example ASSERT-like macros, do different things depending on if _DEBUG or NDEBUG is defined. ASSERT does nothing in a release build, but does checks and abort in debug builds.
The difference between Unicode and non-Unicode is mostly the UNICODE pre-processor macro, which tells header files if certain Unicode functionality should be enabled or not. One thing is that TCHAR will be defined to wchar_t in Unicode builds but as char in non-Unicode builds.
In the debug build you get a lot more error checjking, so if something goes wrong you may get a more informative message ( and it will run more slowly )
In the debug build you will get more information when you run it under the debugger.
You can tell if the build is debug build by looking at the preprocessor definitions of the project properties: _DEBUG will be defined.
You will send the release build to your clients. ( The debug build uses the debug libraries which are not present on most non development machines )
if you want to link a static library to a project, it needs to be compiled with the same settings that you use to compile your code. That's why there is a Debug & a Release version of the library. Additionally, you need to specify whether you want to use unicode or ansi. Here the answer is quite simple (in my opinion) - just use unicode.
What is different in Release compared to Debug so that they can't mix? Mainly it's the memory management. The memory management in Debug does a lot of additional things to allow you to find errors early. As an example, there are canaries that can be checked for overwriting of code. Uninitialized memory is initialized with a specific pattern, ... Additionally, there are a lot of optimizations in release that are not used in debug. This allows release to run faster but makes it difficult to debug the code. Methods might get optimized away and instead are inlined, the parameter passing may be optimized to use registers, ...
So in C++ you manage (at least) 2 configurations. One Debug configuration that you link with the debug library. This one is for developing & testing. And a Release configuration linked with the release library. This one is for delivery. But don't forget that you need to test Release as well as it might behave differently than the Debug configuration.

Using debug/release versions DLL in C++

I am writing an C++ application that could be compiled under Linux (gcc 4.3) and Windows (MS VS08 Express).
My application uses third-party libraries,
On Linux , they are compiled as shared libraries, while
on Windows, there are two versions "Debug" and "Release".
I know that debug version provides extra support for debugging ( just like using -ggdb option in linux gcc, right? )
But I found that if my application is in debug version , the libraries must also be in debug version, otherwise the application will crash.
Why is there such a limit? It seems that there are no such limits in the linux world
Thank you very much!
The Debug configuration of your
program is compiled with full symbolic
debug information and no optimization.
Optimization complicates debugging,
because the relationship between
source code and generated instructions
is more complex.
The Release configuration of your
program contains no symbolic debug
information and is fully optimized.
Debug information can be generated in
PDB Files (C++) depending on the
compiler options used. Creating PDB
files can be very useful if you later
need to debug your release version.
Debug vs Release
It is also possible to debug your release build with the compiler flags.
Debugging Release Builds
Heap Layout - Guard Bytes to prevent overwriting
Compilation - Removing Assert/Debug Info
Pointer Support - Buffers around pointers to prevent seg faults
Optimization - Inline Functions
Common Problems When Creating Release Builds
To elaborate on Martin Tornwall. The various libraries linked when in Debug or Release
LIBCPMT.LIB, Multithreaded, static link, /MT, _MT
LIBCPMTD.LIB, Multithreaded, static link, /MTd, _DEBUG, _MT
CRT Libraries
Most likely, the Release and Debug versions are linked against different versions of the C++ Runtime library. Usually, a Debug build links against the "Multithreaded Debug DLL" runtime, whereas a Release build will generally link against "Multithreaded DLL". Loading DLLs whose runtime libraries are mismatched with that of the application will often lead to mysterious crashes.
You could try verifying that all your DLLs build against the same runtime library as your application, regardless of which configuration (Debug or Release) is active. Whether or not this is desirable is another question entirely.
The ability to choose which runtime library to link with enables the application developer to select the best feature set given her application's requirements. For example, a single-threaded application might incur performance penalties as a result of unnecessary thread synchronization if it is linked with a runtime library that is designed with thread safety in mind. Likewise, the consequences of linking a multi-threaded application against a single-threaded runtime could potentially be disastrous.
While I never intentionally link libraries that were built with different compiler settings, there isn't much point in doing so, I only know of the STL classes in the Dinkumware implementation (the one MSFT uses) to cause this problem.
They support a feature called 'iterator debugging' which is turned on by default in the Debug configuration. This adds members to the classes to aid the diagnostic code. Making them larger. This goes bad when you create the object in a chunk of code that was compiled with one setting and pass it to code that was compiled with the opposite setting. You can turn this off by setting the _HAS_ITERATOR_DEBUGGING macro to 0. Which is rather a major loss, the feature is excellent to diagnose mistakes in the way you use STL classes.
Passing objects or pointers between different libraries is always a problem if you don't carefully control the compile settings. Mixing and matching the CRT version and flavor gets you in trouble when you do so. This normally generates a warning from the linker, not sure what you did to not see it. There won't be one if the code lives in a DLL.

Release mode static library much larger than debug mode version

today i found out that the compiled static library i'm working on is much larger in Release mode than in Debug. I found it very surprising, since most of the time the exact opposite happens (as far as i can tell).
The size in debug mode is slightly over 3 MB (its a fairly large project), but in release it goes up to 6,5 MB. Can someone tell me what could be the reason for this? I'm using the usual Visual Studio (2008) settings for a static library project, changed almost nothing in the build configuration settings. In release, i'm using /O2 and "Favor size or speed" is set to "Neither". Could the /O2 ("Maximize speed") cause the final .lib to be so much larger than the debug version with all the debugging info in it?
EDIT:
Additional info:
Debug:
- whole program optimization: No
- enable function level linking: No
Release:
- whole program optimization: Enable link-time code generation
- enable function level linking: Yes
The difference is specifically because of link-time code generation. Read the chapter Link-Time Code Generation in Compilers - What Every Programmer Should Know About Compiler Optimizations on MSDN - it basically says that with LTCG turned on the compiler produces much more data that is packed into the static library so that the linker can use that extra data for generating better machine code while actually linking the executable file.
Since you have LTCG off in Debug configuration the produced library is noticeably smaller since it doesn't have that extra data.
PS:
Original Link (not working at 11/09/2015)
The optimization could be the issue here, notably automatically created inline functions will be bigger but faster in release than debug.
Personally I've never seen a release PDB be larger than a debug PDB. Same deal for LIBs.