你所不知道的C和C++运行库(一)

2014-11-24 09:57:50 · 作者: · 浏览: 0

你所不知道的C和C++运行库

   周五晚,小雨,少见的未加班。无聊,遂准备写一篇博客,介绍一下C和C++运行库,只因发现工作几年的人对此一知半解的大有人在。
  
  在使用VC构建项目时,经常会遇到下面的链接错误:

\


  初学者面对这些错误常常不知所错:libcmt.lib是什么东西?msvcrtd.dll又是干吗用的?在使用VC++时我们也常常对下面的运行库配置项感到疑惑,它们到底究竟是什么意思呢?甚至一些工作了很多年的程序员也对此一知半解。今天让我们来了解一下它们。
\

从C和C++运行库说起

  为了提高C语言的开发效率,C标准定义了一系列常用的函数,称为C库函数。C标准仅仅定义了函数原型,并没有提供实现。因此这个任务留给了各个支持C语言标准的编译器。每个编译器通常实现了标准C的超集,称为C运行时库(C Run Time Libray) ,简称CRT。对于VC++编译器来说,它提供的CRT库支持C标准定义的标准C函数,同时也有一些专门针对windows系统特别设计的函数。
  与C语言类似,C++也定义了自己的标准,同时提供相关支持库,我们把它称为C++运行时库或C++标准库。
  由于C++对C的兼容性,C++标准库包括了C标准库,除此之外还包括IO流和标准模板库STL。

VC++在何处实现C和C++运行库

  VC++完美的支持C和C++标准,因此也就按照C和C++的标准定义的函数原型实现了上述运行时库。为了方便有不同需求的客户的使用,VC++分别实现了动态链接库DLL版本和静态库LIB版本。同时为了支持程序调试且不影响程序的性能,又分别提供了对应的调试版本。调试版本的名称在Release版本名称后添了字母d。

  对于C运行时库CRT,VC6.0、VC2005、VC2008和VC2010均提供了DLL版本和LIB版本。上述各个编译器提供的LIB版的CRT库,均实现在libcmt.lib。对应的调试版名称为libcmtd.lib。

  而DLL版本名称根据编译器不同而不同,我们可以从名称上加以分辨。
  VC6.使用的CRT库的DLL版本在MSVCRT.DLL中实现, 对应调试版本为MSVCRTD.LIB。
  VC2005使用的CRT库的DLL版本在MSVCR80.DLL中实现,对应调试版本为MSVCR80.DLL。
  VC2008使用的CRT库的DLL版本在MSVCR90.DLL中实现,对应调试版本为MSVCR90D.DLL。
  VC2010使用的CRT库的DLL版本在MSVCR100.DLL中实现,对应调试版本为MSVCR100D.DLL。

  C++标准兼容C标准,但VC各版本将C++编译器使用的C标准库与C编译器使用的C运行库一起实现,它们使用相同的运行库。

  对于C++标准库中的IO流和STL,VC6.0、VC2005、VC2008和VC2010也提供了DLL版本和LIB版本。
  LIB版均实现在libcpmt.lib中,对应的调试版本为libcpmtd.lib。

  不同版本的编译器实现的DLL也不相同。
  VC6.使用的C++类库的 DLL版本在MSVCP60.DLL中实现, 对应调试版本为MSVCP60D.LIB。
  VC2005使用的C++类库的DLL版本在MSVCP80.DLL中实现,对应调试版本为MSVCP80.DLL。
  VC2008使用的C++类库的 DLL版本在MSVCP90.DLL中实现,对应调试版本为MSVCP90D.DLL。
  VC2010使用的C++类库的DLL版本在MSVCP100.DLL中实现,对应调试版本为MSVCP100D.DLL。

  在各个版本的编译器中,我们可以通过配置选项来设置程序使用的C和C++运行时库的类型。如下图(其他版本编译器大同小异):
  
vcTatObQucK2oaPG5NSt0vLKx1ZDNi4wtcS/2NbGzKjP7sS/xKzIz8Xk1sPKx76yzKzBtL3TQ1JUv+KjqLWlz9+zzLDmo6y688Pmu+G96cnco6mhozxiciAvPjxiciAvPravzKyw5qOoRExMo6m6zb6yzKyw5qOoTElCo6lDus1DKyvUy9DQv+K1xNPFyLG14zxiciAvPjxiciAvPqGhoaHS8s6qvrLMrLDmsdjQ67DRQ7rNQysr1MvQ0L/iuLTWxrW9xL+x6rPM0PLW0KOsy/nS1LL6yfq1xL/J1rTQ0M7EvP674bHIvc+086GjzazKsbbU09rKudPDtuC49sSjv+m1xLTz0M3I7bz+wLTLtaOsyOe5+8O/uPbEo7/pvvnRodTxvrLMrMG0vdNDu/JDKyvUy9DQv+KjrNTas8zQ8tTL0NDKsb7Nu+G05tTatuC49tTL0NC/4qGj1NrBtL3TyrHSsrvhs/bP1tbYuLS2qNLltcTOyszio6zI587E1cLK17Xa0rvVxc28y/nKvqGjPGJyIC8+oaGhocq508NETEyw5rXEQ7rNQysr1MvQ0L/io6yzzNDy1NrUy9DQyrG2r8ystcS809TYttTTprXERExMoaOzzNDyzOW7/bHk0KGjrLWr0ru49rrctPO1xM7KzOK+zcrH0ru1qdXSsru1vbbU06ZETEwss8zQ8r2rzt63qNTL0NCho7zZyejKudPDVkM2LjCyotGh1PHKudPDTUTRoc/uubm9qKOsxMfDtLWx08O7p8q508NWQzIwMDXAtMq508PV4rj2RExMyrG63L/JxNyz9s/W1dKyu7W9TVNWQ1JULkRMTLvyTVNWQ1A2MC5ETEy1xMfpv/ahozxiciAvPjxiciAvPqGhoaHU2tXiwO+96cnc0ru49rrcusO1xLmkvt+jukRlcGVuZGVuY3kgV2Fsa2Vyo6y/ydLU08PAtLfWzvZETEy1xNLAwLW52M+1o6zNrMqxsum/tERMTLW8s/a1xLqvyv2jrMq508O3vbeox+tHb29nbGWhozxiciAvPqGhoaHKudPDuMO5pL7ftPK/qk1TVkNSVC5ETEyjrMjnz8LNvKO6PGJyIC8+ICAgPGltZyBzcmM9"https://www.cppentry.com/upload_files/article/49/1_orpcb__.jpg" alt="\" />
  我们可以在其中找到我们经常使用使用的C函数,如printf ,getchar,malloc等。
  打开MSVCP100.DLL,也可以找到这些C函数:

\
  在开发的过程中我们也会遇到如下图的链接错误,LIBCD.lib究竟是何方神圣呢?


  它其实是LIBC.lib的调试版,而LIBC.lib是只有在VC6.0才会使用的静态库,该库是CRT的单线程版,用于支持单线程版本的CRT。VC2005等更高版本的编译器已经不再提供单线程版本,转而使用多线程版的MSVCR80.DLL或libcmt.lib。

  当遇到上