三、功能
运行时库是程序在运行时所需要的库文件,通常以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