【问题标题】:Resolving LNK4098: defaultlib 'MSVCRT' conflicts with解决 LNK4098: defaultlib \'MSVCRT\' 冲突
【发布时间】:2022-01-06 03:04:57
【问题描述】:

这个警告:

LINK : warning LNK4098: defaultlib 'MSVCRT' conflicts
  with use of other libs; use /NODEFAULTLIB:library

是 Visual Studio 中相当常见的警告。我想了解它的确切原因以及处理它的正确方法(如果有的话)。

这出现在调试版本中,使用 /MDd 编译。该项目链接到诸如 Windows Version.dllpdh.dll 之类的东西,它们本身链接到 MSVCRT.dll。显然,我没有这些的调试版本,无法编译它们。

所以我在链接器命令行中添加了/NODEFAULTLIB:MSVCRT,它实际上确实删除了警告。但这实际上是做什么的?为什么有必要?

【问题讨论】:

    标签: visual-studio dll linker warnings msvcrt


    【解决方案1】:

    vclib 中有 4 个版本的 CRT 链接库:

    • libcmt.lib:发布版本 (/MT) 的静态 CRT 链接库
    • libcmtd.lib:用于调试构建的静态 CRT 链接库 (/MTd)
    • msvcrt.lib:CRT 的发布 DLL 版本的导入库 (/MD)
    • msvcrtd.lib:CRT 调试 DLL 版本的导入库 (/MDd)

    查看链接器选项,Project + Properties,Linker,Command Line。注意这里没有提到这些库。链接器会自动找出编译器使用了什么 /M 开关,以及应该通过 #pragma comment 指令链接哪个 .lib。有点重要,如果 /M 选项和你链接的 .lib 不匹配,你会得到可怕的链接错误并且很难诊断运行时错误。

    当链接器被告知链接到 msvcrt.lib 时,您会看到引用的错误消息libcmt.lib。如果将使用 /MT 编译的代码链接到使用 /MD 链接的代码,就会发生这种情况。 CRT 只能有一个版本。

    /NODEFAULTLIB tells the linker to ignore the #pragma comment directive that was generated from the /MT compiled code. This might work, although a slew of other linker errors is not uncommon. Things like 错误号,它在静态 CRT 版本中是一个 extern int,但在 DLL 版本中被宏化为一个函数。许多其他人也是这样。

    好吧,以正确的方式解决这个问题,找到您正在链接的使用错误的 /M 选项编译的 .obj 或 .lib 文件。如果您不知道,那么您可以通过搜索“/MT”的 .obj/.lib 文件来找到它

    顺便说一句:Windows 可执行文件(如 version.dll)有自己的 CRT 版本来完成它们的工作。它位于 c:windowssystem32,你不能可靠地将它用于你自己的程序,它的 CRT 标头在任何地方都不可用。您的程序使用的 CRT DLL 具有不同的名称(如 msvcrt90.dll)。

    【讨论】:

    • 感谢这篇文章,我一直在寻找一个仍在使用 /MDd 的 .lib,我终于找到了一个!谢谢,+1
    • 我刚刚学会的一个技巧是在附加链接器选项中添加 /verbose:lib 来追踪引入错误 CRT 库的库。它显示了 .lib 文件的加载顺序,让您可以看到错误的加载位置。
    • 汉斯,这有多危险?如果我们不能修复它(我们从我们的供应商那里得到一个编译好的库),我们可能会面临什么后果?
    • 我发现 @obmarg' 评论很有用,但仍然不确定如何使用详细输出,直到我找到 msdn.microsoft.com/en-us/library/aa267384(v=vs.60).aspx,它说详细输出只会告诉您链接问题中涉及的所有运行时库。您仍然需要确定哪个链接输入已使用冲突的运行时库进行编译。
    • @buzz3791 使用 /verbose 代替 /verbose:lib。显示的信息包括库搜索过程并列出每个库和对象名称(带有完整路径)、从库中解析的符号以及引用该符号的对象列表。 /verbose 可以显示找到引起冲突的坏人所需的所有信息。
    【解决方案2】:

    这意味着依赖的 dll 之一是使用不同的 run-time library 编译的。

    项目 -> 属性 -> C/C++ -> 代码生成 -> 运行时库

    遍历所有的库,看看它们是以相同的方式编译的。

    此链接中有关此错误的更多信息:

    warning LNK4098: defaultlib "LIBCD" conflicts with use of other libs

    【讨论】:

    • 这就是错误的原因!谢谢你的提示。
    • 对于经验不足的程序员来说,这是最好的答案。
    【解决方案3】:

    来自Yochai Timmer 的 IMO this link 非常好并且相关但阅读起来很痛苦。我写了一个总结。

    Yochai,如果你读过这篇文章,请看最后的注释。


    原帖阅读:warning LNK4098: defaultlib "LIBCD" conflicts with use of other libs

    错误

    LINK:警告 LNK4098:默认库“LIBCD”与其他库的使用冲突;使用 /NODEFAULTLIB:库

    意义

    系统的一部分被编译为使用带有静态链接的调试信息 (libcd) 的单线程标准 (libc) 库

    而系统的另一部分被编译为使用多线程标准库,没有调试信息,它驻留在 DLL 中并使用动态链接

    如何解决

    • 忽略这个警告,毕竟它只是一个警告。但是,您的程序现在包含相同函数的多个实例。

    • 使用链接器选项 /NODEFAULTLIB:lib。这不是一个完整的解决方案,即使您可以让您的程序以这种方式链接,您也忽略了一个警告标志:代码已针对不同的环境编译,您的一些代码可能是针对单线程模型编译的,而其他代码是多线程。

    • [...] 搜索您所有的图书馆并确保它们具有正确的链接设置

    在后者中,正如原帖中提到的那样,可能会出现两个常见问题:

    • 您有一个第三方库,它以不同的方式链接到您的应用程序。

    • 您的代码中嵌入了其他指令:通常这是 MFC。如果系统中的任何模块都链接到 MFC,则所有模块名义上都必须链接到同一版本的 MFC。

    对于这些情况,请确保您了解问题并在解决方案中做出决定。


    注意:我想将 Yochai Timmer 链接的摘要包含到他自己的答案中,但由于有些人无法正确审查编辑,我不得不将其写在一个单独的答案中。对不起

    【讨论】:

      【解决方案4】:

      每次我想在 VC++ 中创建应用程序时,我都会得到这个。

      右键单击该项目,选择“属性”,然后在“配置属性”下选择“属性”。 C/C++ |代码生成”,为调试配置选择“多线程调试(/MTd)”。

      请注意,这不会更改您的发布配置的设置 - 您需要转到同一位置并为发布选择“多线程 (/MT)”。

      【讨论】:

        【解决方案5】:

        右键单击该项目,选择“属性”,然后在“配置属性”下选择“属性”。链接器 |输入 |忽略特定库并写入 msvcrtd.lib

        【讨论】:

          猜你喜欢
          • 2011-03-01
          • 1970-01-01
          • 2016-06-15
          • 1970-01-01
          • 2012-10-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多