8

I am building my application in debug mode using VS 2017. I have built the 3rd party libraries in release mode that it depends on and links to. Is this allowed or is that the cause of the reported error.

LNK2038 mismatch detected for 'RuntimeLibrary': value 'MT_StaticRelease' doesn't match value 'MTd_StaticDebug' in xxx.obj   my-application  <path-to>\libboost_filesystem-mt-s.lib(path_traits.obj) 1   

This page states:

RuntimeLibrary Indicates the version of the C++ Standard Library and C runtime that's used by an app or library. Code that uses one version of the C++ Standard Library or C runtime is incompatible with code that uses a different version. For more information, see /MD, /MT, /LD (Use Run-Time Library).

I understand that the DLL runtime library can't be mixed with the non-DLL library. Is the same true for the debug and release libraries?

I haven't had any problems doing the same thing on Linux.

ksl
  • 4,519
  • 11
  • 65
  • 106
  • 2
    Yes, the same is true for debug and release libraries. You can not mix. – Some programmer dude Mar 05 '18 at 12:06
  • 1
    You can't mix Debug and Release and also you should also note that the Visual Studio 2017 is binary compatible with 2015 only. All other versions are incompatible. What that means is they will have differences in the standard library implementation and they will have a different CRT. The latter problem can and will lead to heap corruption if memory is allocated in one CRT and freed in the other. – drescherjm Mar 05 '18 at 13:12
  • MSFT crt library back-compatibility is not as good as linux, side-by-side way is used, but recently ucrt is introduced, it may improve the situation. For the projects with third-party library, it is suggested to request thirdparty to provide the binary built with /MT, it may decrease link issues caused by the different VS versions and debug/release configuration. – ravin.wang Mar 05 '18 at 13:37
  • Does this answer your question? [LNK2038: mismatch detected for 'RuntimeLibrary': value 'MT\_StaticRelease' doesn't match value 'MD\_DynamicRelease' in file.obj](https://stackoverflow.com/questions/28887001/lnk2038-mismatch-detected-for-runtimelibrary-value-mt-staticrelease-doesn) – talonmies Dec 03 '19 at 06:15
  • You cannot mix the CRT inside one executable (because linker will choose only one - either debug or release), but you can use different CRTs if you link different executable modules. E.g. you can compile your app using Debug CRT and use DLL built with Release CRT. The only requirement is the ABI between app and DLL must be CRT neutral. – Dmytro Ovdiienko Feb 17 '22 at 12:57

1 Answers1

4

No, you cannot mix debug and release runtime libraries with Visual Studio 2017. They are not ABI compatible.

There additional checks and member variables for debug checks in the C++ runtime and the memory allocation routines add additional space and checks in debug mode.

Example code taken from <xmemory0> (_Adjust_manually_vector_aligned)

    // Extra paranoia on aligned allocation/deallocation; ensure _Ptr_container is
    // in range [_Min_back_shift, _Non_user_size]
  #ifdef _DEBUG
    constexpr uintptr_t _Min_back_shift = 2 * sizeof(void *);
  #else /* ^^^ _DEBUG ^^^ // vvv !_DEBUG vvv */
    constexpr uintptr_t _Min_back_shift = sizeof(void *);
  #endif /* _DEBUG */
    const uintptr_t _Back_shift = reinterpret_cast<uintptr_t>(_Ptr) - _Ptr_container;
    _STL_VERIFY(_Back_shift >= _Min_back_shift && _Back_shift <= _Non_user_size, "invalid argument");

Here the _DEBUG variant of the function allocates additional 2 * sizeof(void*) for checks, whereas the release variant uses only sizeof(void*).

From here it is quite obvious that a pointer created by the release variant and used by the debug variant (or vice versa) would trigger all kinds of confusion and error checks.

Hence the Linker error to prevent this from happening.


That said, it would be possible to mix them under specific circumstances, although I would not recommend it.

You must basically create two partitions, which have a very tight and narrow interface. You must make sure that no data of any kind except PODs or fully opaque data types are transferred between "partitions". Also you cannot statically link both debug and release libraries (because of ABI and symbol clashes) to the same binary.

So you could create an std::string in your 'Debug' routine, but wouldn't be allowed to pass this to a 'Release' routine. But you would be able to pass the 'std::string::c_str()' return value to the 'Release' routine, because that is just a pointer to char.

To do that you would put all 'release' binaries in one DLL and statically link this DLL with the static 'release' runtime and put all 'debug' binaries in another DLL (or EXE) and statically link this with the 'debug' runtime. That way the runtimes are completely hidden inside their respective DLLs and are not visible to the outside world.

(It is possible to link one or more DLLs with a static runtime and others with the dynamic runtime. But again, I wouldn't recommend it).

Basically this is what happens, when you run your 'debug' application under Windows. You don't need a 'Debug' Windows to run your 'Debug' application. Your 'Debug' application runs fine with the 'Release' Windows, which is using its own 'release' runtimes. It's just that the 'release' runtime used by Windows is completely hidden from your 'debug' release time.

Hajo Kirchhoff
  • 1,969
  • 8
  • 17