一、什么叫C运行库:
1、由来:
C运行库,即C Runtime library,简称CRT。
C语言是小内核语言,其本身只处理少量的关键字、数据类型和基本流程控制。其内核开发出来后,C语言重写了Unix的90%的系统函数,并提取最常用的部分,形成了头文件和Lib库,C运行库产生。换言之,此时使用C语言本身和C运行库,在Unix下开发。
运行库包括C程序运行的最基本的函数,规模几近数千个函数。比如通过main开始运行,exit退出,printf之类的函数、错误处理等。换言之,没有运行库std,C程序根本不能运行。
2、Ansi C标准和 Standard Library
C逐渐流行,不同的编译厂商,在不同的平台上实现了Standard Library,当然都是平台相关的,这对于程序员而言显然带来紊乱。于是有了Ansi C标准,该标准除了详细定义C语言各要素的具体含义外, 同时规定了Standard Library的标准。因此Std由各编译厂商根据Ansi标准提供。
3、C++的标准库:
C++的Standard C++ Library,包括上面的C 运行库和Stl,显然,由于C++是C的超级,C运行库被简单的加入,没有必要另写一套。
二、VC++里的C运行库
在vs中,同一解决方案,每个项目应使用相同的C运行库。我们在解决方案资源管理器中,选中项目|右键|属性,打开该项目的属性页:配置属性|C/C++|代码生成,可以选择"运行库",有四个选择:多线程(/MT),多线程调试(/MTD),多线程Dll(/MD),多线程Dll调试(/MDD)。这四个选择,MT和MD是release版本,MTD和MDD是Debug版本,所以我们只要弄清MT和MD的区别。 /MT 即multithread, static version,多线程静态版本。这种方式下,编译器静态的链接LIBCMT.lib。/MD是multithread- and DLL-specific version,多线程DLL版本。这种方式下,编译器链接MSVCRT.lib,而动态的使用MSVCRT*.dll。它们的区别是:
1、静态运行时,使用LIBCMT.lib。动态运行时使用MSVCRT.lib+MSVCRT*.dll。
2、使用静态运行库,CRT会链接进EXE文件,生成的EXE文件大些,但运行时不用加载CRT。使用动态运行库,编译的EXE文件小些,但程序启动后需要Load CRT,加载MSVCRT*.dll文件,性能略低。
三、VC中C运行库设定的铁律:
1、同一解决方案,各项目使用相同的运行库设置,否则不仅可能无法生成,即使通过编译,也会带来多种潜在隐患
2、使用第三方库,必须编译和项目设置相同的版本,如果不能,则只能弃用。3、如果使用动态运行时/MD或/MDD,则MFC应用程序,只能选择在共享Dll中使用MFC,不能静态链接MFC。反过来说,如果MFC要静态链接到Exe文件,则必须使用/MT或/MTD
四、常见的编译错误:
当解决方案不同项目的运行库设置不同的时候,首先会出现一堆类似如下的错误:
MSVCRTD.lib(MSVCR120D.dll) : error LNK: _memmove 已经在 libcmtd.lib(memmove.obj) 中定义
然后:
LINK : warning LNK4098: 默认库“MSVCRTD”与其他库的使用冲突;请使用 /NODEFAULTLIB:library
fatal error LNK1169: 找到一个或多个多重定义的符号
原因很简单,Mfc应用和Dll项目之间,在链接另一个项目的类似lib、obj时,很明显,由于运行库设置不同,编译器面对两个运行库,选择链接哪一个运行库的函数,显然是很困难的事情,只好简单的告诉你:编译失败。将两者的运行库设置改为一致...无论哪一个,一致就好,问题解决。一些文章提到的另外两种解决方式:1、人为的忽略一个库;2、强制编译,都是有隐患的,某种意义上来说,是误导。请遵循上面提到的铁律:同一解决方案中,所有项目使用相同的运行库设置。