检测到“RuntimeLibrary”的 LNK2038 不匹配:值“MT_StaticRelease”与 xxx.obj 中的值“MTd_StaticDebug”不匹配

ksl*_*ksl 5 c++ visual-studio visual-c++-runtime

我正在使用 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   
Run Code Online (Sandbox Code Playgroud)

页面指​​出:

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

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

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

Haj*_*off 5

不可以,您不能将调试和发布运行时库与 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");
Run Code Online (Sandbox Code Playgroud)

这里_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 使用的“发布”运行时完全隐藏在您的“调试”发布时间之外。