Vistual C++ 中的C运行时库浅析

Vistual C++ 中的C运行时库浅析(转)

一、历史

  C运行时库就是C run-time library,诞生于20世纪70年代,是C而非C++语言
世界的概念,C程序运行时需要这些库中的函数。

  C语言是所谓的“小内核”语言,就其语言本身来说很小(不多的关键字,程序
流程控制,数据类型等)。所以,C语言内核开发出来之后,Dennis Ritchie和
Brian Kernighan就用C本身重写了90%以上的UNIX系统函数,并且把其中最常用的
部分独立出来,形成头文件和对应的LIBRARY,C运行时库就是这样形成的。

  随着C语言的流行,各个C编译器的生产商/个体/团体都遵循老的传统,在不同
平台上都有相对应的Standard Library,但大部分实现都是与各个平台有关的。由
于各个C编译器对C的支持和理解有很多分歧和微妙的差别,所以就有了ANSI
C;ANSI C(主观意图上)详细的规定了C语言各个要素的具体含义和编译器实现要
求,引进了新的函数声明方式,同时订立了Standard Library的标准形式。所以C
运行时库由编译器生产商提供。至于由其他厂商/个人/团体提供的头文件和库函
数,应当称为第三方C运行库(Third party C run-time libraries)。

二、发展

  C运行时库诞生时是单线程的,随着操作系统多线程技术的发展,最初的C运行
时库无法满足程序的需求。

  到了C++世界里(C++是C的超集),有了另外一个概念:Standard C++
Library(VC针对C++加入的Standard C++ Library主要包
括:LIBC.LIB,LIBCMT.LIB和MSVCRT.LIB。),它包括了上面所说的C run-time
library和STL。

  Windows环境下,Visual C++提供了两种版本的C运行时库:一个版本供单线程
应用程序调用,另一个版本供多线程应用程序调用。

  Visual C++提供的多线程运行时库又分为静态链接库和动态链接库两类,而每
一类运行时库又可再分为Debug版和Release版,因此Visual C++共提供了6个运行
时库。

三、功能

  运行时库是程序在运行时所需要的库文件,通常以LIB或DLL形式提供:

  C运行时库                                库文件
  Single thread(static link)               libc.lib
  Debug single thread(static link)         libcd.lib
  MultiThread(static link)                 libcmt.lib
  Debug multiThread(static link)           libcmtd.lib
  MultiThread(dynamic link)                msvcrt.lib
  Debug multiThread(dynamic link)          msvcrtd.lib

  C运行时库包含了C程序运行的最基本和最常用的函数。

  C运行时库除了给我们提供必要的库函数调用之外,它提供的另一个最重要的
功能是为应用程序添加启动函数。

  C运行时库启动函数的主要功能为进行程序的初始化,对全局变量进行赋初
值,加载用户程序的入口函数。

四、编译器链接选项

  VC带的编译器名字叫cl.exe,它有几个与标准程序库有关的选项:/ML、
/MLd、/MT、/MTd、/MD、/MDd。编译时到底哪个C运行时库联入程序取决于这些编
译选项,选项告诉编译器应用程序想使用什么版本的C标准程序库:

  /ML对应单线程静态版的标准程序库(libc.lib);
  /MT对应多线程静态版标准库(libcmt.lib),此时编译器会自动定义_MT宏;
  /MD对应多线程DLL版(导入库msvcrt.lib,DLL是msvcrt.dll),编译器自动
定义_MT和_DLL两个宏。

  后面加d的选项都会让编译器自动多定义一个_DEBUG宏,表示要使用对应标准
库的调试版,因此:

  /MLd对应调试版单线程静态标准库(libcd.lib);
  /MTd对应调试版多线程静态标准库(libcmtd.lib);
  /MDd对应调试版多线程DLL标准库(导入库msvcrtd.lib,DLL是msvcrtd.dll)。

  即:

  /ML 使用LIBC.lib创建单线程可执行文件
  /MLd 使用LIBCD.lib创建调试单线程可执行文件
  /MT 使用LIBCMT.lib创建多线程可执行文件
  /MTd 使用LIBCMTD.lib创建调试多线程可执行文件
  /MD 使用MSVCRT.lib创建多线程DLL
  /MDd 使用MSVCRTD.lib创建调试多线程DLL

  说明:

  (1)静态链接的单线程库

  静态链接的单线程库只能用于单线程的应用程序,C运行时库的目标代码最终
被编译在应用程序的二进制文件中。
  通过/ML编译选项可以设置Visual C++使用静态链接的单线程库。

  (2)静态链接的多线程库

  静态链接的多线程库的目标代码也最终被编译在应用程序的二进制文件中,但
是它可以在多线程程序中使用。
  通过/MT编译选项可以设置Visual C++使用静态链接的多线程库。

  (3)动态链接的运行时库

  动态链接的运行时库将所有的C库函数保存在一个单独的动态链接库
MSVCRTxx.DLL中,MSVCRTxx.DLL处理了多线程问题。
  使用/MD编译选项可以设置Visual C++使用动态链接的运行时库。

  /MLd、/MTd或/MDd选项使用Debug Runtime Library(调试版本的运行时刻函
数库),与/ML、/MT或/MD分别对应。Debug版本的Runtime Library包含了调试信
息,并采用了一些保护机制以帮助发现错误,加强了对错误的检测,因此在运行性
能方面比不上Release版本。

  程序运行时,很大一部分时间是在这些运行库里运行。在程序(Release版)
被编译时,VC会根据编译选项(单线程、多线程或DLL)自动将相应的运行时库文
件(libc.lib、libcmt.lib或Import library msvcrt.lib)链接进来。

  注:修改编译选项,将/MD或/MDd改为/MT或/MTd,就实现了对VC运行时库的静
态链接,在运行时就不再需要VC的dll了。

五、附:

  下面是MSDN关于Visual C++编译器选项的说明:

  这些选项选择单线程或多线程运行时例程,指示多线程模块是否为DLL,并选
择运行时库的发布版本或调试版本。

  /MD

  使应用程序使用运行时库的多线程并特定于DLL的版本。定义_MT和_DLL,并使
编译器将库名MSVCRT.lib放入.obj文件中。
  用此选项编译的应用程序静态链接到MSVCRT.lib。该库提供允许链接器解析外
部引用的代码层。实际工作代码包含在MSVCR80.DLL中,该库必须在运行时对于与
MSVCRT.lib链接的应用程序可用。
  当在定义了_STATIC_CPPLIB(/D_STATIC_CPPLIB)的情况下使用/MD时,它将导
致应用程序与静态多线程标准C++库(libcpmt.lib)而非动态版本(msvcprt.lib)链
接,同时仍通过msvcrt.lib动态链接到主CRT。

  /MDd

  定义_DEBUG、_MT和_DLL,并使应用程序使用运行时库的调试多线程并特定于
DLL的版本。它还使编译器将库名MSVCRTD.lib放入.obj文件中。

  /ML

  使编译器将库名LIBC.lib放入.obj文件中,以便链接器使用LIBC.lib解析外部
符号。这是编译器的默认操作。LIBC.lib不提供多线程支持。

  /MLd

  定义_DEBUG并使编译器将库名LIBCD.lib放入.obj文件中,以便链接器使用
LIBCD.lib解析外部符号。LIBCD.lib不提供多线程支持。

  /MT

  使应用程序使用运行时库的多线程静态版本。定义_MT并使编译器将库名
LIBCMT.lib放入.obj文件中,以便链接器使用LIBCMT.lib解析外部符号。

  /MTd

  定义_DEBUG和_MT。此选项还使编译器将库名LIBCMTD.lib放入.obj文件中,以
便链接器使用LIBCMTD.lib解析外部符号。

  /LD

  创建 DLL。
  将/DLL选项传递到链接器。链接器查找DllMain函数,但并不需要该函数。如
果没有编写 DllMain函数,链接器将插入返回TRUE的DllMain函数。
  链接DLL启动代码。
  如果命令行上未指定导出(.exp)文件,则创建导入库(.lib);将导入库链接到
调用您的DLL的应用程序。
  将/Fe(命名EXE文件)解释为命名DLL而不是.exe文件;默认程序名成为
basename.dll而不是basename.exe。
  除非显式指定/MD,否则将暗指/MT。

  /LDd

  创建调试DLL。定义_MT和_DEBUG。

  警告

  不要混合使用运行时库的静态版本和动态版本。在一个进程中有多个运行时库
副本会导致问题,因为副本中的静态数据不与其他副本共享。链接器禁止在.exe文
件内部既使用静态版本又使用动态版本链接,但您仍可以使用运行时库的两个(或
更多)副本。例如,当与用动态(DLL)版本的运行时库链接的.exe文件一起使用
时,用静态(非DLL)版本的运行时库链接的动态链接库可能导致问题。(还应该
避免在一个进程中混合使用这些库的调试版本和非调试版本)。

  注:/ML、/MLd貌似已经不提供;另,LIBC.LIB,LIBCMT.LIB和MSVCRT.LIB有
对应的LIBCP.LIB,LIBCPMT.LIB和MSVCPRT.LIB,作用不清楚,不知道是升级替换
版本还是升级补充版本或其他功能,待续-_-!...OY~orz

 

你可能感兴趣的:(Vistual C++ 中的C运行时库浅析)