error LNK2005,解决办法
错误信息:
testLib.lib : error LNK2005: 已经在 msvcprtd.lib(MSVCP90D.dll) 中定义
libcpmtd.lib: error LNK2005: 已经在 msvcprtd.lib(MSVCP90D.dll) 中定义
发生情况:
test.exe调用静态库json_vc71_libmtd.lib时。
test.exe运行库选多线程 DLL (/MD),
testLib.lib运行库选的是多线程调试(/MT)。 会报此错误
原因:
因为工程同时连结了LIBCMTD.lib与MSVCRTD.lib.所以造成函数定义版本冲突。也就是说,程序连接器已经在一个CRT的版本中找到所需的函数定义,但此时又跳出另外一个CRT,也给了一份相同函数的实现版本,所以连接器无法判断应该忽略谁,并且选择谁。
静态运行时库:LIBCMTD.lib
动态运行时库:MSVCRTD.lib
解决方法:
a、使程序和要调用的库所选的运行库相同。
b、忽略冲突的库。
引发的思考
为了提高C语言的开发效率,C标准定义了一系列常用的函数,称为C库函数。C标准仅仅定义了函数原型,并没有提供实现。因此这个任务留给了各个支持C语言标准的编译器。每个编译器通常实现了标准C的超集,称为C运行时库(C Run Time Libray),简称CRT。
VC++完美的支持C和C++标准,因此也就按照C和C++的标准定义的函数原型实现了上述运行时库。为了方便有不同需求的用户使用,VC++分别实现了动态链接库DLL版本和静态LIB版本。同时为了支持程序调试且不影响程序的性能,又分别提供了对应的调试版本。(VS项目属性中C/C++运行库 MT /MTd /MD /MDd)调试版本的名称在Release版本名称后添了字母d
/MT是"multithread, static version" 意思是多线程静态的版本,定义了它后,编译器把LIBCMT.lib安置到OBJ文件中,让链接器使用LIBCMT.lib 处理外部符号。
/MD是"multithread- and DLL-specific version",意思是多线程DLL版本,定义了它后,编译器把MSVCRT.lib安置到OBJ文件中,它连接到DLL的方式是静态链接,实际上工作的库MSVCR80.DLL。
即:
静态运行时库: | LIBCMT.lib |
动态运行时库: | MSVCRT.lib +MSVCR80.DLL |
多线程(/MT):链接LIB版的C和C++运行库。在链接时就会在将C和C++运行时库集成到程序中成为程序中的代码,程序体积会变大。
多线程调试(/MTd):LIB的调试版。
多线程DLL(MD):使用DLL版的C和C++运行库,这样在程序运行时会动态的加载对应的DLL,程序体积会减小,缺点是在系统没有对应DLL时程序无法运行。
多线程调试DLL(MDd):表示使用DLL的调试版
简单的说:
(1)/MD,表示运行时库由操作系统提供一个DLL,程序里不集成。
(2)/MT,表示运行时库由程序集成,程序不再需要操作系统提供运行时库DLL