Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LNK2038 mismatch detected for 'RuntimeLibrary': value 'MT_StaticRelease' doesn't match value 'MTd_StaticDebug' in xxx.obj

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.

like image 991
ksl Avatar asked Nov 18 '22 18:11

ksl


1 Answers

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.

like image 127
Hajo Kirchhoff Avatar answered Jun 04 '23 03:06

Hajo Kirchhoff