这个警告:

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

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

这在调试版本中出现,使用/MDd编译。该项目链接到windows Version.dll和pdh.dll,它们本身链接到MSVCRT.dll。显然,我没有这些文件的调试版本,无法编译它们。

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


当前回答

在vc\lib中有4个版本的CRT链接库:

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

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

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

/NODEFAULTLIB告诉链接器忽略从/MT编译代码生成的#pragma注释指令。这可能会起作用,尽管大量其他链接器错误并不罕见。比如errno,它在静态CRT版本中是一个extern int,但在DLL版本中被宏化为一个函数。很多人都喜欢这样。

好吧,用正确的方法解决这个问题,找到你正在链接的.obj或.lib文件,该文件是用错误的/M选项编译的。如果你没有线索,那么你可以通过grep .obj/找到它。“/MT”的lib文件

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

其他回答

在vc\lib中有4个版本的CRT链接库:

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

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

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

/NODEFAULTLIB告诉链接器忽略从/MT编译代码生成的#pragma注释指令。这可能会起作用,尽管大量其他链接器错误并不罕见。比如errno,它在静态CRT版本中是一个extern int,但在DLL版本中被宏化为一个函数。很多人都喜欢这样。

好吧,用正确的方法解决这个问题,找到你正在链接的.obj或.lib文件,该文件是用错误的/M选项编译的。如果你没有线索,那么你可以通过grep .obj/找到它。“/MT”的lib文件

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

这意味着其中一个依赖dll是用不同的运行时库编译的。

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

检查所有的库,看看它们是否以相同的方式编译。

有关此错误的更多信息,请参见此链接:

默认库“LIBCD”与使用其他库冲突

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

右键单击项目,选择“配置属性| C/ c++ |代码生成”下的属性,选择“多线程调试(/MTd)”进行调试配置。

注意,这不会改变你的发布配置的设置-你需要到相同的位置,并选择“多线程(/MT)”发布。

在我看来,Yochai Timmer的这个链接非常好,也很相关,但读起来很痛苦。我写了一个总结。

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


对于原始帖子,请阅读:警告LNK4098: defaultlib“LIBCD”与其他库的使用冲突

错误

LINK:警告LNK4098: defaultlib“LIBCD”与其他库的使用冲突;使用/ NODEFAULTLIB:图书馆

意义

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

如何解决

Ignore the warning, after all it is only a warning. However, your program now contains multiple instances of the same functions. Use the linker option /NODEFAULTLIB:lib. This is not a complete solution, even if you can get your program to link this way you are ignoring a warning sign: the code has been compiled for different environments, some of your code may be compiled for a single threaded model while other code is multi-threaded. [...] trawl through all your libraries and ensure they have the correct link settings

在后者中,就像在最初的帖子中提到的那样,会出现两个常见的问题:

您有一个第三方库,它以不同的方式链接到您的应用程序。 代码中还嵌入了其他指令:通常这是MFC。如果系统中的任何模块链接到MFC,那么所有模块必须在名义上链接到相同版本的MFC。

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


注意:我想把Yochai Timmer的链接的摘要包含在他自己的回答中,但由于有些人很难正确地审查编辑,我不得不在一个单独的回答中写下它。对不起

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