其实the Universal CRT(通用C运行时库)已经不能算是“下一代”,由于它已经在前两年伴随着Visual Studio 2015和Windows10发布。可是因为以前使用VS2015开发的应用还较少,关注的人也少,相关的文章更少。因此笔者想干脆用一篇文章,深刻浅出的介绍一下Universal CRT。php
CRT,也就是“C Runtime”,中文译为:C运行时。咱们一直称为C Runtime Library(C运行时库)。它主要负责实现C程序在运行时的各类抽象功能实现。不一样的C编译器会有不一样的具体实现程序,好比Windows下常见的微软的VC编译器的msvcrt.dll;GCC/Glibc的crt0.o、crti.o等。具体到二进制表现形式,能够是动态库,也能够是静态库。redis
CRT通常会至少负责如下功能:windows
CRT也能够当作是一个操做系统抽象层。你们都知道,每一种操做系统都有本身的API或者是系统调用。像C语言之因此可以跨平台(代码级),就是由于我只须要用C库函数写程序,CRT会转化为相应平台的具体实现的API来处理。api
下面咱们要着重讨论的是Windows下的开发工具Visual C++配套的CRT,如下将统称为“VC运行时库”。多线程
(注:上表中的划代是做者本身的划代方式)app
我记得我最先学C语言仍是上大二(2002年)的时候,那时但是VC的黄金年代。额~~应该说是钻石年代。你们都在学习VC++6.0,一个堪称经典的版本。VC++6.0是为了配合Windows98的应用软件开发而发布的,发布的年代也差很少就是98年先后,因此内部有些文件又称之为VC98。函数
到这个时候,VC运行时库文件只有一个叫msvcrt.dll的,通常在c:\windows\system32下,你们发行软件产品的时候,基本上不须要考虑是否须要带个什么库,由于默认操做系统都会自带的。工具
逐渐的,你们发现一个很是棘手的问题,那就是随着功能的增多,不一样版本的msvcrt.dll支持的功能和函数不一样,版本的识别和兼容成了难题。当时不少安装包为了本身的须要,会不停的覆盖系统的msvcrt.dll,致使运行不稳定。若是把WinXP系统的msvcrt.dll覆盖了Win98的,那会致使WinXP不稳定。因此后来就发展除了第二代的CRT。学习
自从微软发布Visual Studio.Net 2002/2003开始,为了解决日益增加的功能和DLL版本兼容性问题,微软给现有的运行时库加上了版本号,而且把运行时库拆分为多个文件,比较常见的是msvcrXXX.dll和msvcpXXX.dll。其中XXX是版本号。开发工具
版本号的定义和文件命名以下表所示:
其中msvcrXXX.dll(注意不是msvcrtXXX.dll)通常负责实现C语言的基础特性,如程序启动、异常处理、库函数等功能。msvcpXXX.dll负责标准C++库的相关实现。你们能够看看其中的导出函数就能明白。
在这一阶段中,开发者想要发布软件产品,就必须确保目标计算机上必须已经安装了相应版本的运行时库。通常状况下,微软推荐你们使用运行时库安装包来进行安装。对于大型软件为了预防万一,都会附带vcredist.exe安装包。可是这种方法很不受待见。由于如今大多数软件都是经过互联网进行分发,对安装包大小很敏感。每次打包附带一个运行时库包,既增长了用户的下载时间,又增长了推广成本。
如今大部分软件的作法是将这两个dll放在软件目录下发行。可是问题又来了,光是VC2008的msvcr90.dll的就有N个版本,不一样语言有不一样版本,随着update增长的修正版本也不少。大部分状况应该不会有问题,但笔者就曾经遇到过加载错误版本的运行时库而程序崩溃又查不出问题的经历。这个时候微软要求必须使用manifest文件来指定加载的VC运行时库版本。直到VC2010,因为编译器内置了manifest,因此就不须要额外提供。
自Visual Studio 2010开始,微软大力改进了不少C++特性,陆续在20十二、201三、2015版本中增长了对C9九、C++十一、C++1四、C++17等标准的支持,使得C++库的功能成倍增长。这种小步快跑的更新模式,使得如何有效的让VC运行时库向前和向后兼容而不破坏现有的软件组件的问题变得异常突出。再加上让VC运行时库可以更好的支持Win8/10提倡的PC和移动设备并举的理念,微软团队决定在Visual Studio 2015对VC运行时库进行重构。而后“the Universal CRT”就应运而生了。
the Universal CRT(如下简称UCRT),顾名思义,意思为“通用C运行时库”。关键就在“通用”这两个字上。早期的设计理念就是要把相对通用的功能独立出来。这个概念最先在Visual Studio 14 (即vs2015)的CTP1 [1] 发布的时候提出来 [2] 。VS很神奇的跳过了13.0这个版本,直接从12.0(vs2013)跳到了14.0(vs2015),估计是由于欧美人把13这个数字认为是不吉利的有关。尽管UCRT的版本号称是1.0,但真实的VCRuntime仍是14.0。
当vs2015还在CTP阶段时,微软的设想是将VC运行时库拆分红三部分。
vcruntime140.dll 包含运行期须要处理的功能,如:进程启动、异常处理、以及耦合到相关编译器的功能。
appcrt140.dll包含全部平台上均可用的全部功能,且之后保持这部分CRT的向后兼容性。包括:堆、数学库、stdio库、locale库、大多数字符串操做函数、时间库和一些其余功能等。
desktopcrt140.dll包含全部只能由桌面应用程序使用的功能,且之后保持这部分CRT的向后兼容性。包括:处理多字节字符串、exec和spawn进程管理函数、direct-to-console I/O函数的功能等等。
在最终发布正式版的时候,微软将appcrt140.dll和desktopcrt140.dll合并为一个不带版本号的程序库:ucrtbase.dll。它对应的Debug版本的命名是ucrtbased.dll。这个后来被正式命名为“the Universal CRT”。
令不少人吐槽的是,UCRT并不仅是一个DLL,它还附带了一堆以“api-ms-”开头的DLL程序文件,且有40个之多!能够看到,这些DLL导出了几乎全部的win32api。这实际上是微软在Windows10中大力推进的“Universal Windows Platform (UWP) apps”即“通用Windows平台应用”的api接口 [3] 。这些dll有些默认为“delay load”,也就会是被延迟加载。通常基于UCRT编译的程序,不是直接调用ucrtbase.dll,而是调用VCRuntime140.dll和UWP apis来间接调用。
若是你是用Visual Studio 2015和2017来编写C或C++程序,那么就已是基于UCRT的。
VCRuntime140.dll 这是VC运行时库和编译器相关的必备模块,必须存在。
msvcp140.dll 若是你写的程序含有C++标准库的代码,那就必须存在。
ucrtbase.dll和api-ms-**.dll 必须存在。
第一种
微软强烈推荐使用vcredist.exe来给目标机安装相应的文件。它会安装全部对的UCRT文件和必备组件。这是最省事儿便捷的方法。
可是vcredist_x86.exe和vcredist_x64.exe就各有近14MB的体积!大型程序发布的时候可能无所谓,而不少不少基于互联网发布的程序,却不可能这么干。互联网程序对安装包的大小很敏感,这直接影响最终用户终端的到达率和推广成本。
可参考PHP7.1的Windows版的下载页面和安装包。
第二种
程序自带VCRuntime140.dll和msvcp140.dll,再给系统打基于msu的KB2999226补丁。KB2999226补丁会给系统安装UCRT。通常状况下,Windows10已经自带了UCRT,不须要额外打补丁。
这种方法不适用于WinXP系统。而在中国WinXP系统还有很大保有量,你们都不会轻易放弃这个庞大的用户群的。
可参考Python 3.5的Windows安装包。
第三种
如今互联网程序大多使用的是app-local的部署模式,意思就是把依赖库放在本身程序目录下,既不会跟别的应用软件冲突,又方便了软件分发。
起初,微软并无打算针对UCRT程序继续这样的部署模式。可是后来你们反响比较强烈,因此在Windows 10 SDK发布的时候,把UCRT和UMP的相关dlls都一块儿发布了。这个目录通常是“C:\Program Files (x86)\Windows Kits\10\Redist\ucrt”。
你也能够在Visual Studio 2015的安装目录下找到VCRuntime140.dll和msvcp140.dll。这个目录通常是“C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x86\Microsoft.VC140.CRT”。
有些开发者一开始可能会被ucrt目录下的四十几个文件吓到,不过还好都不大,打包压缩之后都很小。
可参考Visual Studio 2015配套的Remote Debugger 调试工具。这个工具因为要求是“standalone”的,因此就是用此方法部署的。能够在这里找到:“C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Remote Debugger\x86”。
UCRT的确给咱们带来了不少全新的概念,也给咱们带来了少量的不适应。但这毕竟是将来的发展方向。基于UCRT的Visual Studio 2015给咱们带来的众多新的C、C++语言标准的支持,我相信之后C++程序会变得更增强大。按照网上的一些说法,将来不排除会对VCRuntime模块再次优化重构的可能性,这个咱们只能拭目以待了。Visual Studio 2017即将发布,咱们也将继续跟进UCRT的发展方向。
[1] CTP 即Community Technology Preview,译为社区技术预览版,通常是微软开发软件的早期对内测试版
[2] 参考 https://blogs.msdn.microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/
[3] 参考: https://msdn.microsoft.com/zh-cn/library/mt186421.aspx
from:http://www.qingpingshan.com/m/view.php?aid=223329