Mixing STL debug/release libraries - c++

I'm aware that mixing debug and release libraries that pass STL containers to each other causes big problems. But what exactly in 'debug' or 'release' causes this?
I have a QT project that gets built as 'release', but it has /DEBUG added to the compiler flags.
If I build another QT project under 'debug' (which also has the /DEBUG flag), are they compatible?
Or is there an optimization flag or some other flag that makes them incompatible?
Basically, is there a way I can look at the compilation line of the 2 libraries and see something that says "DON'T MIX THESE!"?

This is undefined behaviour, so it might work but more probably it will crash your app. It also depends on stl implementation, in debug version it might enable additional checks and allocate additional memory making data layout different in release modes. In the end this violates ODR rule (one definition rule) once again causing undefined behaviour.
I have a QT project that gets built as 'release', but it has /DEBUG added to the compiler flags. If I build another QT project under 'debug' (which also has the /DEBUG flag), are they compatible?
If your Release contains exactly the same compiler flags as Debug then I would say they are compatible.
Or is there an optimization flag or some other flag that makes them incompatible?
you should be able to see those flags, I dont think optimization flags should cause UB problems, its rather different macros used during compilation phase that cause ODR violation. Maybe there are optimization flags which changes alignment in structures...
Basically, is there a way I can look at the compilation line of the 2 libraries and see something that says "DON'T MIX THESE!"?
no idea here.
Why are you mixing differently build libraries in the first place? this is asking for trouble.

Not really. Concerning Visual C++'s STL implementation, there are data members of the containers corresponding to the iterator checking that is only compiled in if some preprocessor variables are set. These variables are default valued base on the NDEBUG preprocessor variable that is quasi standard for "no debug". But these could be also set directly from the command line, or from header files, or Visual Studio property pages, etc.
E.g.: all containers are derived from _Container_base, while that is a typedef depending on _ITERATOR_DEBUG_LEVEL. The different _Container_base implementations have different memory layout, and that is what causes incompatibilities between the debug and release version.
The /DEBUG compiler flag tells the compiler whether to generate debug information or not, and might also affect default values for optimization settings, but I am not sure about that, and of course that is compiler dependent.
Just like there could be an STL implementation that does not depend on any preprocessor directives, and in that case it would not matter how you compile it, debug or release, the memory layout would be identical, and so it could be passed around between modules compiled the different ways.

Firstly the /DEBUG flag doesn't actually create a 'debug' build. It just tells the linker to generate debugging information and create a .pdb file along with the resulting binary.
As to the difference between the debug and release MSVC++ runtimes the issue is to do with the fact that different runtimes can have different sizes for the same object. e.g. in debug extra information might be placed in iterators to ensure their validity at run time. If code has been compiled against the release version of these structures then corruption is likely. Another issue would be if an object if allocated from the heap of one runtime and is attempted to be freed on the heap of another runtime.

Related

ABI Compatibility between release and debug

When using GCC, given that I compile the same library sometimes in release and sometimes in debug, is the ABI guaranteed to be compatible?
(while using the same compiler)
I have an executable and some shared objects (some depend on others), I want to be able to swap out release/debug shared objects without recompiling everything but
only the shared objects in interest.
Is this possible, or is there some scenario where I might get some undefined behavior this way? (Assuming my code is strictly packed, and padded in both release and debug)
EDIT:
I'll elaborate on the problem we're seeing. We have a custom version of intrusive_ptr, in debug mode we have our own intrusive_ptr which has a single member that is a boost::intrusive_ptr, and in release we simply use boost::intrusive_ptr. The API of our intrusive_ptr is the same of boost::intrusive_ptr, and we don't have any virtual functions in the class.
What we are seeing is this:
If we use all debug libs or all release libs all works well. If we mix debug executable with release libs, there is a memory leak from the intrusive_ptr and it does not release the object.
The sizeof our intrusive_ptr and boost::intrusive_ptr are identical, both in debug and release (our class does not add any size overhead on top).
So I am wondering what could be causing the leak, ABI difference are the only things that come to mind.
Ideas?
I have known several compilers that generate incompatible code for release and debug (though these compilers are long since deprecated). In face I would not trust object modules to fully compatible unless they have been compiled with Exactly the same flags.
This is why makefiles (following GNU principles) and IDE like Eclipse build release/debug/profile objects into different directories. To make sure that they can never be mixed up.
Typically no, because the usual difference between a release and a debug build are just options to make debug stepping works better. But unexpected behavior is still possible, if you define other options differently (such as integer size, target architecture, ??) between the release and debug builds, the caller parameters may not match the callee expectations. There could also be issues with exception safety, and const-ness that the run time linker may not check.

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.

STL and release/debug library mess

I'm using some 3rd party. I'm using it's shared library version, since the library is big (~60MB) and is used by several applications.
Is there a way at application startup to find out that release/debug version of library is used respectively for release/debug version of my application?
Longer description
The library which exposes C++ interface. One of API methods return std::vector<std::string>.
The problem when I compile my application in debug mode, debug version of the library should be used. Same for release. If incorrect version of the library is used application is crashed.
According to gcc (see http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt03ch17s04.html)
but with a mixed mode standard library
that could be using either debug-mode
or release-mode basic_string objects,
things get more complicated
P.S. 1
It looks like proposal of Timbo is a possible solution - use different soname for debug and release libraries. So, what should be passed to ./configure script to change library soname?
P.S. 2
My problem is not at link time, but rather at run time.
P.S. 3
Here is question demonstrating problem I is facing with.
The debug mode referenced here has nothing to do with debug or release build of your application. The STL debug mode is activated with -D_GLIBCXX_DEBUG and is a special checking mode.
It is very unlikely that the 3rd party library was in fact compiled with STL checking mode, but if it was, it would likely very promptly mention that your code should also be compiled with -D_GLIBCXX_DEBUG.
If the 3rd party library was not built with checking STL, then it is compatible with your code regardless of whether you are doing optimized or debug build.
Since you state that debug build of your code linked with optimized build of 3rd party library causes a crash, that crash is most likely caused by a bug in your code (or possibly by a bug in 3rd party library).
Valgrind and GDB are your friends.
I believe that you have misread the documentation at the link you provide. In particular, you've misunderstood its purpose -- that section is entitled "Goals", and describes a number of hypothetical designs for a C++ debug library and the consequences of those designs in order to explain the actual design choices that were made. The bits of text that follow the lines you quoted are describing the chaos that would result from a hypothetical implementation that had separate designs for release-mode and debug-mode strings. It goes on to say:
For this reason we cannot easily provide safe iterators for the std::basic_string class template, as it is present throughout the C++ standard library.
(Or, rephrasing that, providing a special "debug" version of string iterators is impossible.)
...
With the design of libstdc++ debug mode, we cannot effectively hide the differences between debug and release-mode strings from the user. Failure to hide the differences may result in unpredictable behavior, and for this reason we have opted to only perform basic_string changes that do not require ABI changes. The effect on users is expected to be minimal, as there are simple alternatives (e.g., __gnu_debug::basic_string), and the usability benefit we gain from the ability to mix debug- and release-compiled translation units is enormous.
In other words, the design of the debug and release modes in GCC's libstdc++ has rejected this hypothetical implementation with separate designs for the strings, specifically in order to allow cross-mode linking of the sort that you are worrying about how to avoid.
Thus, you should not have problems with compiling your library once, without -D_GLIBCXX_DEBUG (or with it, if for some reason you prefer), and linking it with either mode of your application. If you do have problems, it is due to a bug somewhere. [But see edit below! This is specific to std::string, not other containers!]
Edit: After this answer was accepted, I followed up in answering the follow-up question at std::vector<std::string> crash, and realized that the conclusion of this answer is incorrect. GCC's libstdc++ does clever things with strings to support "Per-use recompilation" (in which all uses of a given container object must be compiled with the same flags, but uses of the same container class within a program need not be compiled with the same flags), but that is not the same thing as complete "Per-unit compilation" that would provide the cross-linking ability you need. In particular, the documentation says of that cross-linking ability,
We believe that this level of recompilation is in fact not possible if we intend to supply safe iterators, leave the program semantics unchanged, and not regress in performance under release mode....
Thus, if you're passing containers across your library interface, you will need two separate libraries. Honestly, for this situation I've found that the easiest solution is just to install the two libraries into different directories (one for each variant -- and you'll want both to be separate from your main library directory). Alternately, you can rename the debug library file and then install it manually.
As a further suggestion -- you're presumably not running this in debug mode very often. It may be worth only compiling and linking the debug version statically into your application, so you don't have to worry about installing multiple dynamic libraries and keeping them straight at runtime.
Give the debug and release versions of the DLL different names and link the correct one through library dependency. Your application then wont start unless it finds the correct DLL.
This is the sort of check you should be doing in your build system. In your build script,
if you're building for release then link against the release library.
if you're building for debug then link against the debug library.
For instance, if you're using make:
release: $(OBJ)
$(CC) $(CXXFLAGS_RELEASE) $(foreach LIB,$(LIBS_RELEASE),-l$(LIB))
debug: $(OBJ)
$(CC) $(CXXFLAGS_DEBUG) $(foreach LIB,$(LIBS_DEBUG),-l$(LIB))

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.

C++ visual studio libraries

Is there any way to make static libraries built in Microsoft Visual Studio independent from used CRT (with debug support / without it)?
I mean like, for simple C library it is possible to generate code using gcc and then use the same static library in visual studio. The resulting library.a file is completely independent from /MT or /MDd switches and does not result in warning / linking errors.
Comparing to Visual Studio default behaviour, you would have to build two versions of the same library - for Debug / Release modes independently. If you try to use the Release version in Debug configuration or vice-versa, this results in ugly warnings (warning LNK4098: defaultlib "LIBCMT" ...), but sometimes does not compile due to different runtimes?
Is there any way to avoid this? Or probably I'm doing something wrong?
To make a lib that will link in regardless of runtime selection it is necessary to use two switches:
/MT to build against the basic release runtime, /Zl to omit the default library names.
Building against the dll runtimes will cause the compiler to decorate all the runtime symbols with __imp_ (so, for example, it will try and link against __imp__fread rather than _fread). So you have to choose one of the static runtimes.
The compiler does an implicit default library pragma, depending on the lib selected:
#pragma comment(lib,"libcmtd.lib")
is how it looks in code. The /Zl causes the compiler to omit all these directives - (implicit and explicit) from the resulting .obj (and hence .lib) file. So the result will should link cleanly without causing default library conflicts.
No. The object files for the default release and debug configurations are completely different -- debug object binaries are relocatable machine executable object code, release object binaries are simply an intermediate representation of the original code. That is, the backend is in the linker for release builds, but is in the compiler for debug builds. Putting the backend is in the Linker allows the compiler back end to make more intelligent decisions with respect to optimization of your program, at the expense of longer compilation times.
Is there a problem with distributing 2 versions of the library? I don't claim to speak for everybody, but I always like to have a debug version, compiled against the static debug libs, with asserts and extra checking compiled in. (Symbols are good, too, of course!) The asserts and checks are helpful, the stack traces are usually better when the thing crashes in the library code, and it's often easier to read the disassembly.