检测到"运行时库"的不匹配LNK2038:值"MT_StaticRelease"与 xxx.obj 中的值"MTd_StaticDebug"不匹配

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

本文关键字:不匹配 xxx obj StaticDebug MTd StaticRelease LNK2038 运行时 检测 MT      更新时间:2023-10-16

>我正在使用VS 2017在调试模式下构建我的应用程序。我已经在它依赖和链接的发布模式下构建了第 3 方库。这是允许的还是报告错误的原因。

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   

本页指出:

运行时库 指示应用或库使用的 C++ 标准库和 C 运行时的版本。使用一个版本的 C++ 标准库或 C 运行时的代码与使用不同版本的代码不兼容。有关详细信息,请参阅/MD、/MT、/LD(使用运行时库)。

我知道 DLL 运行时库不能与非 DLL 库混合使用。调试库和发布库也是如此吗?

我在 Linux 上做同样的事情没有任何问题。

不可以,不能将调试和发布运行时库与 Visual Studio 2017 混合使用。它们与 ABI 不兼容。

在C++运行时中,用于调试检查的其他检查和成员变量以及内存分配例程增加了额外的空间,并在调试模式下进行了检查。

示例代码取自<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");

在这里,函数的_DEBUG变体为检查分配额外的2 * sizeof(void*),而发布变体仅使用sizeof(void*)

从这里很明显,由发布变体创建并由调试变体使用的指针(反之亦然)会触发各种混淆和错误检查。

因此,链接器错误可以防止这种情况发生。


也就是说,在特定情况下可以混合它们,尽管我不建议这样做。

您基本上必须创建两个分区,它们具有非常紧密和狭窄的接口。您必须确保在"分区"之间传输除 POD 或完全不透明的数据类型之外的任何类型的数据。此外,不能将调试库和发布库(由于 ABI 和符号冲突)静态链接到同一二进制文件。

因此,您可以在"调试"例程中创建std::string,但不允许将其传递给"发布"例程。但是你可以将 'std::string::c_str()' 返回值传递给 'Release' 例程,因为它只是一个指向 char 的指针。

为此,您可以将所有"发布"二进制文件放在一个 DLL 中,并将此 DLL 与静态">

发布"运行时静态链接,并将所有"调试"二进制文件放在另一个 DLL(或 EXE)中,并将其与"调试"运行时静态链接。这样,运行时就完全隐藏在各自的 DLL 中,对外界不可见。

(可以将一个或多个 DLL 与静态运行时链接,将其他 DLL 与动态运行时链接。但同样,我不推荐它)。

基本上,当您在Windows下运行"调试"应用程序时,就会发生这种情况。您不需要"调试"Windows即可运行"调试"应用程序。您的"调试"应用程序在"发布"Windows上运行良好,该Windows使用自己的"发布"运行时。只是Windows使用的"发布"运行时在您的"调试"发布时间中完全隐藏。