【问题标题】:LNK2038 mismatch detected for 'RuntimeLibrary': value 'MT_StaticRelease' doesn't match value 'MTd_StaticDebug' in xxx.obj检测到“RuntimeLibrary”的 LNK2038 不匹配:值“MT_StaticRelease”与 xxx.obj 中的值“MTd_StaticDebug”不匹配
【发布时间】:2018-03-05 11:59:24
【问题描述】:

我正在使用 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   

This 页面状态:

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

我了解 DLL 运行时库不能与非 DLL 库混合使用。调试库和发布库也一样吗?

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

【问题讨论】:

  • 是的,调试和发布库也是如此。不能混用。
  • 你不能混合调试和发布,你还应该注意 Visual Studio 2017 仅与 2015 二进制兼容。所有其他版本均不兼容。这意味着它们将在标准库实现方面存在差异,并且它们将具有不同的 CRT。如果内存在一个 CRT 中分配并在另一个 CRT 中释放,则后一个问题可能并且将导致堆损坏。
  • MSFT crt 库的后向兼容性不如linux,使用的是side-by-side方式,但最近引入了ucrt,可能会改善这种情况。对于有第三方库的项目,建议要求第三方提供使用/MT构建的二进制文件,这样可以减少由于VS版本和调试/发布配置不同而导致的链接问题。
  • 您不能在一个可执行文件中混合 CRT(因为链接器只会选择一个 - 调试或发布),但如果您链接不同的可执行模块,则可以使用不同的 CRT。例如。您可以使用 Debug CRT 编译您的应用程序并使用使用 Release CRT 构建的 DLL。唯一的要求是应用程序和 DLL 之间的 ABI 必须是 CRT 中立的。

标签: c++ visual-studio visual-c++-runtime


【解决方案1】:

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

C++ 运行时中的调试检查和内存分配例程增加了额外的空间和调试模式下的检查。

示例代码取自&lt;xmemory0&gt; (_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*),而release 变体仅使用sizeof(void*)

从这里很明显,一个指针 created 由 release 变体和 used 由 debug 变体(反之亦然)会引发各种混乱和错误检查。

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


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

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

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

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

可以将一个或多个 DLL 链接到静态运行时,而将其他 DLL 链接到动态运行时。但同样,我不建议这样做)。

当您在 Windows 下运行“调试”应用程序时,基本上会发生这种情况。您不需要“调试”窗口来运行“调试”应用程序。您的“调试”应用程序在使用自己的“发布”运行时的“发布”Windows 上运行良好。只是 Windows 使用的“发布”运行时对您的“调试”发布时间完全隐藏。

【讨论】:

    猜你喜欢
    • 2019-04-17
    • 2015-05-07
    • 2021-01-29
    • 2016-12-30
    • 2016-06-24
    • 2014-12-06
    • 2021-12-23
    • 2018-05-05
    • 2023-03-13
    相关资源
    最近更新 更多