30

Is it a bad practice to use a release version of 3rd party library in debug binary?

I am using a 3rd party library and compiled a release .lib library. My exe is in debug mode development. Then I got:

error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in test1.obj

After some googling I found that is because I am trying to mix release with debug, and I should probably compile the library in debug mode or otherwise muddle with the _ITERATOR_DEBUG_LEVEL macro. But I am just curious if that is the recommanded way and why. It just seem cumbersome that I need to compile and keep a record of both release and debug binaries for every 3rd party library I intend to use, which will be many very soon, while having no intention to debug into these code.

M W
  • 1,269
  • 5
  • 21
  • 31
  • 1
    Are you unable to contact this 3rd party to get a debug version or build a debug version yourself? – Jesse Good Jul 25 '12 at 21:35
  • It's more than bad practice: it is almost guaranteed that the program will either crash or do Bad Things. Before VS2010 you could link anyway, to discover at runtime strange bugs. Now at least you're prevented to. – Alexandre C. Jul 25 '12 at 21:40
  • 1
    @JesseGood Yes I have the source code and I have just compiled the debug version. Problem solved. I was just wondering if I can get away with compiling and keeping track of one mode. Apparently not! – M W Jul 25 '12 at 21:58
  • It is on windows but it shouldn't. Compiling everything in debug mode can give total unacceptable program speed and turnaround times. Consider building the webkit engine and using it in debug mode or some interpreter language. But as answers say, you might get away with it when using DLL without dynamic runtime DLL linkage – Lothar Nov 06 '20 at 21:13
  • @AlexandreC. Are you sure about VS2010? You say VS2010 also fails. But now I move from VS2010 to VS2019 and see this error for the first time. – kuga Jun 07 '21 at 15:27
  • @kuga I don't remember specifics from 10 years ago. It used to be possible to mismatch runtimes, now it's not possible and you're really not supposed to anyway. – Alexandre C. Jun 07 '21 at 17:51

3 Answers3

35

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.

tinman
  • 6,348
  • 1
  • 30
  • 43
  • In particular, the std containers and iterators are different and incompatible. That's the check you are seeing: it affects the layout of the iterators by adding extra fields. The std::string stuff (only) has support for compatibility between Debug and Release, but nothing else in stl will work at all. – JDługosz Sep 15 '14 at 22:44
  • 4
    @JDługosz std::string is explicitly not compatible between runtimes. An entertaining exercise is create a DLL with only the function `__declspec(dllexport) std::string make_string()`, build in Debug, then build a Release executable, link and call the function. When I tried to `std::cout` the returned string, the resulting crash was quite dramatic. This is using VS2013, but it was certainly a problem with VS2010 and I expect other versions as well. [Here's](https://blogs.msdn.microsoft.com/vcblog/2014/06/10/the-great-c-runtime-crt-refactoring/) a little info from the horse's mouth. – Rai May 26 '16 at 07:13
  • Well, the particular version I had dug into had code to make debug and release std string (iterator or value; not remember anymore) intercompatible. I do beleive that was older than the VS2010, but I don't recall exactly how long ago it was. – JDługosz May 26 '16 at 19:39
  • 1
    Though, on linux when you use package managers, you get prebuilt versions of libraries for only optimized configuration AFAIK. Only Windows seems to have this separated debug v release concept which makes maintaining prebuilt dependencies a giant pain in the rear. Prior to VS2010 it was always perfectly fine to link release (optimized) libs with debug executables. ABI compatibility shouldn't change between configurations. – void.pointer May 17 '17 at 21:22
  • @tinman Based on the premise of the last sentence,whether I could mixing debug and release code?In turn,mix a release application with debug DLLs.Passing the STL objects how to influence. – Crawl.W Nov 20 '18 at 03:49
  • 1
    And what if you don't have access to the debug libraries? You're SOL? – Emperor Eto Jul 04 '20 at 12:45
  • 1
    I'm curious why mixing Debug and Release libraries using gcc is no problem, but using MSVC all hell breaks loose? – CraigDavid Apr 28 '23 at 03:39
18

Mixing debug and release library/binary is good and very useful practice.

Debugging a large solution (100+ projects as an example) typically is not fast or even could not be possible at all (for an example when not all projects can be built in debug). Previous commentators wrote that debug/release binary could have different alignment or another staff. It's not true. All linking parameters are same in debug and release binaries because they depends on the same architecture.

You have to remove all optimizations (/Od) from the selected project. Then assign a release c++ runtime.

The issue came because you have defined _DEBUG in the project. Remove the macro from the definitions (Project->Properties->Preprocessor->Preprocessor Definitions).

If the macro isn't in the Preprocessor Definitions, then you have to add it in "UndefinePreprocessorDefinitions".

Tania Chistyakova
  • 3,928
  • 6
  • 13
  • 3
    I totally agree. It's common practice (at least in linux world). You don't want to debug 3d party libs, and basically i can't w/o sources. – RedEyed Sep 06 '19 at 14:03
  • I kept selecting the non-debug CRT but it wasn't working. The _DEBUG macro definition likewise was the culprit. Thanks for this info! – Emperor Eto Jul 04 '20 at 12:50
6

The fact that it doesn't compile should be sufficient to prove it's bad practice.

Regarding maintaining separate builds - you don't need to do that. Here's a workaround that previously worked for me:

#ifdef _DEBUG
#define DEBUG_WAS_DEFINED
#undef _DEBUG
#endif

#include <culprit>

#ifdef DEBUG_WAS_DEFINED
#define _DEBUG
#endif

Let me know if this works for you.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625