其實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