C运行时库

Visual Studio文档的新主页是docs.microsoft.com上的Visual Studio 2017文档

可以在CRT Library Features中找到该主题的最新版本。

本主题讨论构成C运行时库的各种.lib文件及其关联的编译器选项和预处理程序指令。

 

C运行时库(CRT)

C运行时库(CRT)是包含ISO C99标准库的C ++标准库的一部分。实现CRT的Visual C ++库支持本机代码开发,支持混合本机代码和托管代码,以及用于.NET开发的纯托管代码。所有版本的CRT都支持多线程开发。大多数库既支持静态链接,也支持将库直接链接到代码中,或支持动态链接以使代码使用常见的DLL文件。

在Visual Studio 2015中,CRT已经重构为新的二进制文件。Universal CRT(UCRT)包含标准C99 CRT库导出的函数和全局变量。UCRT现在是Windows组件,并作为Windows 10的一部分提供。现在可以在Windows 10 SDK中找到UCRT的静态库,DLL导入库和头文件。安装Visual C ++时,Visual Studio安装程序会安装使用UCRT所需的Windows 10 SDK子集。您可以在Visual Studio 2015支持的任何Windows版本上使用UCRT。您可以使用vcredist为Windows 10以外的受支持Windows版本重新分发它。有关详细信息,请参阅重新分发Visual C ++文件

下表列出了实现UCRT的库。

图书馆 相关的DLL 特点 选项 预处理程序指令
libucrt.lib 没有 将UCRT静态链接到您的代码中。 /公吨 _公吨
libucrtd.lib 没有 用于静态链接的UCRT的调试版本。不可再发行。 / MTD _DEBUG,_MT
ucrt.lib ucrtbase.dll 用于UCRT的DLL导入库。 / MD _MT,_DLL
ucrtd.lib ucrtbased.dll 用于UCRT的Debug版本的DLL导入库。不可再发行。 / MDD _DEBUG,_MT,_DLL

vcruntime库包含Visual C ++ CRT特定于实现的代码,例如异常处理和调试支持,运行时检查和类型信息,实现细节和某些扩展库函数。该库特定于所用编译器的版本。

此表列出了实现vcruntime库的库。

图书馆 相关的DLL 特点 选项 预处理程序指令
libvcruntime.lib 没有 静态链接到您的代码中。 /公吨 _公吨
libvcruntimed.lib 没有 用于静态链接的调试版本。不可再发行。 / MTD _MT,_DEBUG
vcruntime.lib vcruntime <版本>的.dll 用于vcruntime的DLL导入库。 / MD _MT,_DLL
vcruntimed.lib vcruntime <版本> d.dll Debug vcruntime的DLL导入库。不可再发行。 / MDD _DEBUG,_MT,_DLL

根据CRT库是静态链接还是动态链接,还是本机,托管或混合代码,初始化CRT的代码位于多个库之一。此代码处理CRT启动,内部每线程数据初始化和终止。它特定于所用编译器的版本。即使使用动态链接的UCRT,此库也始终静态链接。

此表列出了实现CRT初始化和终止的库。

图书馆 特点 选项 预处理程序指令
LIBCMT.LIB 将本机CRT启动静态链接到您的代码中。 /公吨 _公吨
libcmtd.lib 静态链接本机CRT启动的调试版本。不可再发行。 / MTD _DEBUG,_MT
MSVCRT.LIB 用于本机CRT启动的静态库,用于DLL UCRT和vcruntime。 / MD _MT,_DLL
MSVCRTD.LIB 用于DLL UCRT和vcruntime的本机CRT启动的Debug版本的静态库。不可再发行。 / MDD _DEBUG,_MT,_DLL
msvcmrt.lib 用于混合本机和托管CRT启动的静态库,用于DLL UCRT和vcruntime。 / CLR  
msvcmrtd.lib 用于DLL UCRT和vcruntime的混合本机和托管CRT启动的Debug版本的静态库。不可再发行。 / CLR  
msvcurt.lib 纯托管CRT的静态库。 / CLR:纯  
msvcurtd.lib 用于纯托管CRT的Debug版本的静态库。不可再发行。 / CLR:纯  

如果从命令行链接程序而没有指定C运行时库的编译器选项,则链接器将使用静态链接的CRT库:libcmt.lib,libvcruntime.lib和libucrt.lib。

使用静态链接的CRT意味着C运行时库保存的任何状态信息都将是CRT实例的本地信息。例如,如果在使用静态链接的CRT时使用strtok,_strtok_l,wcstok,_wcstok_l,_mbstok,_mbstok_l,则strtok解析器的位置strtok与同一进程中的代码中使用的状态无关(但在不同的DLL或EXE中)它链接到静态CRT的另一个实例。相反,动态链接的CRT为动态链接到CRT的进程内的所有代码共享状态。如果您使用这些功能的新的更安全版本,则此问题不适用; 例如,strtok_s没有这个问题。

因为通过链接到静态CRT构建的DLL将具有其自己的CRT状态,所以不建议静态链接到DLL中的CRT,除非特别期望和理解其后果。例如,如果在加载链接到其自己的静态CRT的DLL的可执行文件中调用_set_se_translator,则DLL中的代码生成的任何硬件异常都不会被转换程序捕获,但主可执行文件中的代码生成的硬件异常将被抓住了

如果使用/ clr编译器开关,则代码将与静态库msvcmrt.lib链接。静态库在托管代码和本机CRT之间提供代理。您不能将静态链接的CRT(/ MT/ MTd选项)与/ clr一起使用。请改用动态链接库(/ MD/ MDd)。

如果您使用的是/ clr:pure编译器开关,则您的代码将与静态库msvcurt.lib链接。与/ clr一样,您无法链接静态链接库。

有关将CRT与/ clr一起使用的更多信息,请参阅混合(本机和托管)程序集 ; for / clr:pure,请参阅Pure and Verifiable Code(C ++ / CLI)

要构建应用程序的调试版本,必须定义_DEBUG标志,并且应用程序必须与其中一个库的调试版本链接。有关使用库文件的调试版本的更多信息,请参阅CRT调试技术

此版本的CRT不完全符合C99标准。特别是,不支持<tgmath.h>头和CX_LIMITED_RANGE / FP_CONTRACT pragma宏。某些元素(例如标准IO函数中参数说明符的含义)默认使用传统解释。您可以使用/ Zc编译器一致性选项并指定链接器选项来控制库一致性的某些方面,

 

标准C ++库

标准C ++库 特点 选项 预处理程序指令
LIBCPMT.LIB 多线程,静态链接 /公吨 _公吨
MSVCPRT.LIB 多线程,动态链接(MSVCP <version> .dll的导入库) / MD _MT,_DLL
LIBCPMTD.LIB 多线程,静态链接 / MTD _DEBUG,_MT
MSVCPRTD.LIB 多线程,动态链接(MSVCP <版本> D.DLL的导入库) / MDD _DEBUG,_MT,_DLL

当您构建项目的发布版本时,默认情况下链接其中一个基本C运行时库(LIBCMT.LIB,MSVCMRT.LIB,MSVCRT.LIB),具体取决于您选择的编译器选项(多线程,DLL,/ CLR)。如果在代码中包含一个头文件参考,则标准C ++库将在编译时由Visual C ++自动链接。例如:

#include <ios>   

 

如果应用程序使用多个CRT版本会出现什么问题?

如果您有多个DLL或EXE,那么您可能有多个CRT,无论您是否使用不同版本的Visual C ++。例如,将CRT静态链接到多个DLL可能会出现同样的问题。使用静态CRT遇到此问题的开发人员已被指示使用/ MD进行编译以使用CRT DLL。如果您的DLL通过DLL边界传递CRT资源,您可能会遇到CRT不匹配的问题,需要使用Visual C ++重新编译项目。

如果您的程序使用多个版本的CRT,则在跨越DLL边界传递某些CRT对象(例如文件句柄,语言环境和环境变量)时需要注意。有关所涉及的问题以及如何解决它们的更多信息,请参阅跨DLL边界传递CRT对象的潜在错误

猜你喜欢

转载自blog.csdn.net/qq_41786318/article/details/81319642