Mixing Debug and Release Library/Binary - Bad Practice

Mixing debug and release library/binary - bad practice?

Mixing debug and release code is bad practice. The problem is that the different versions can depend on different fundamental parts of the C++ runtime library, such as how memory is allocated, structures for things like iterators might be different, extra code could be generated to perform operations (e.g. checked iterators).

It's the same as mixing library files built with any other different settings. Imagine a case where a header file contains a structure that is used by both application and library. The library is built with structure packing and alignment set to one value and the application built with another. There are no guarantees that passing the structure from the application into the library will work since they could vary in size and member positions.

Is it possible to build your 3rd party libraries as DLLs? Assuming the interface to any functions is cleaner and does not try to pass any STL objects you will be able to mix a debug application with release DLLs without problems.

Mixing debug and release libraries: Windows vs Linux, static vs shared

Yes Linux and Windows are different. I cannot tell much for Windows, but with Linux toolchains we don't really have a split Debug vs Release build.

What we have is several options:

  • which optimizations are enabled?
  • should debugging symbols be emitted?
  • some other less relevant stuff.

What build toolchain refer as "Release" or "Debug" is just a set of options. for instance, CMake's min-size release build uses -Os -DNDEBUG, while CMake's debug release uses -g. Distributions also add additional options when they package stuff.

But other than those options, the ABI is the same, so those are all compatible (except for options specifically marked[*] - but those are not used in typical builds). So it doesn't matter. You can mix "debug" or "release" objets, it will work.

As for 4), the way a lot of distributions do it is they build with split debugging symbols. That means debugging information is emitted in a separate file, and typically packaged independently. For instance:

ii  libc6:amd64       2.27-3ubuntu1  GNU C Library: Shared libraries
ii libc6-dbg:amd64 2.27-3ubuntu1 GNU C Library: detached debugging symbols

Second package is normally not installed. I installed it manually to step through libc6 with full debug info.


[*] For an exemple, check out GCC code generation options. You'll see those that generate incompatible objects have a warning on them.

Are Boost Debug and Release Libraries the same?

Boost will typically build both debug and release libraries by default and install them both in the library install directory. (Usually c:\Boost\lib on windows or /usr/local on unix/linux, etc). However, this behaviour can be changed, so you should check.

If you look in the library you should see both versions for every library, for example:

libboost_unit_test_framework-vc110-mt-1_53.lib
libboost_unit_test_framework-vc110-mt-gd-1_53.lib

The first one above is the release version of the library, while the -gd in the seconds indicates a debug build, see this page for the naming convention used.

Now, you must make sure you link with the correct version of the library. If you are using Visual Studio, then it will select the correct library for you. For other toolsets you must explicitly choose the correct library to link with for each build configuration.

Note: Visual Studio includes a pragma option to specify what library an object file should link against. Boost makes use of this option via the auto_link.hpp header file which will be included for you if you use a boost library that has a library to link against.

size of library is bigger in release mode then debug mode in VS2010

You should compare your build settings, esp. optimization and library linking (static / dynamic). If you are unsure, copy your command line for both linker and compiler and we can check it for you here.

The command line can be found in the build log, or in project Properties / C/C++ / Command Line and Properties / Linker / Command Line.

For compiler the most important settings to look for are /O, /M.

For linker I would look esp. for /OPT.

Your compiler switches are:

/c /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D WIN32 /D NDEBUG /D _LIB /D _UNICODE /D UNICODE /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TP /analyze- /errorReport:prompt GuruxDLMS\GXDateTime.cpp

What is causing your library to be big is /GL. For explanation see Release mode static library much larger than debug mode version.

Is it possible to link a debug mode compiled library to a project in release mode?

Is it possible to link a debug mode complied library to a project in release mode?

Yes. Debug mode only means there are assertions, debug symbols included, etc. The debug version of the library should be fully functional just like the release version (although it might run slower/consume more memory than a release build).

Edit: as David Rodriguez-dribeas points out, this can yield undefined behavior if a definition of an inline function is different in release and debug mode, as it then violates the one definition rule.

what considerations should I care about working with libraries?

That's too broad to be answered on StackOverflow.

Linking against library in release and .exe in debug crashes in Visual studio

You don't have to use the same runtimes for release and debug modules (but it helps), as long as you follow very specific rules: never mix and ,match accessing the memory allocated using each runtime.

To put this more simply, if you have a routine in a dll that allocates some memory and returns it to the caller, the caller must never free it - you must create a function in the original dll that frees the memory. That way you're safe from runtime mismatches.

If you consider that the Windows dlls are built release only (unless you have the debug version of Windows), yet you use them from your debug applications, you'll see how this matters.

Your problem now is that you're using a static library, there is no dll boundary anymore, and the calls in the lib are compiled using the static version of the C runtime. If your exe uses the dynamic dll version of the runtime, you'll find that the linker is using that one instead of the one your static lib used... and you'll get crashes.

So, you could rebuild your lib as a dll; or you could make sure they both use the same CRT library; or you could make sure they both use the same type of CRT - ie the dll version or the static version, whilst keeping debug/release differences.

At least, I think this is your problem - what are the 'code generation, runtime library' settings?

Is loading both release and debug version of MSVCR (or UCRT etc.) officially supported by MS?

Yes, this is supported, and is common.

For example, if you build a C++/CLI Windows Forms app, you'll probably end up loading at least three different CRTs into the process: your program will use msvcr.dll, the CLR will use msvcr120_clr0400.dll, and various operating system components loaded in your process may use msvcrt.dll.

How to make Visual Studio (2019/2022) link to the normal runtime libraries during a debug build?

This is doable and also good practice for remote debugging big and complex applications also exlained in Mixing debug and release library/binary - bad practice?.

Besides switching link libraries from Multi-threaded Debug DLL (/MDd) to Multi-threaded DLL (/MD) one needs to take into account debug macros like _ITERATOR_DEBUG_LEVEL which might otherwise conflict during linking. A typical error message that indicates such a conflic is error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL'

Once all the conflicting macros have been resolved it will link to the standard runtime libraries but the debug symbols for the application remains.

Also, @Adrian Mole thanks for the assistans in this matter.



Related Topics



Leave a reply



Submit