这个警告:
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)。
在我看来,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的链接的摘要包含在他自己的回答中,但由于有些人很难正确地审查编辑,我不得不在一个单独的回答中写下它。对不起
在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)。