close

 

 

 

寫一下這一篇,以防某天老人痴呆忘記如何解,

這問題最主要的原因,就是因為Runtime Library這一個坑,

其實,在Windows下進行C++開發的時候,我們不可避免的需要和Windows的底層進行交互溝通,然而,VS底下有一個機制,不少人都被坑過,特別是當你的Project使用了很多第三方的library的時候,就容易出現Link error相關的問題,比如說啥 LIBCMT.lib(_file.obj) : error LNK2005:  _initstdio already defined in libc.lib(_file.obj) LIBCMT.lib(file.obj) : error LNK2005: endstdio already defined in libc.lib(_file.obj) ,或者叫你說你缺少xxxxxx dll,又或者是你在A電腦開發,開發的非常順利,敲鍵盤的速度就像下雨一般 ( 我同事形容我敲鍵盤的聲音,就跟下雨一樣很吵  哈哈 ) ,然後,把這一隻程式build好後丟到別台電腦,然後,就找不到Library了。

 

諸如此類的問題,有被坑過的............. 可以在底下留言 ! 

 

 

既然這裡這麼容易出問題,那我們就來對這部分進行深入的了解,畢竟,知其然且知其所以然才是正途 ! 您說對吧 ? 

 

1. 什麼是 Runtime Library?

 

Runtime Library 就是所謂運行時庫,也就是簡稱為 CRT( C Run Time Library )的玩意,是我們程式在運行的時候所需要的library文件,而這些文件通常都是以Lib或Dll 的形式提供。

我們看一下有關於CRT在MSDN上的解釋 : 

 

C Run-Time Libraries (CRT)

The C Run-time Library (CRT) is the part of the C++ Standard Library that incorporates the ISO C99 standard library. The Visual C++ libraries that implement the CRT support native code development, and both mixed native and managed code. All versions of the CRT support multi-threaded development. Most of the libraries support both static linking, to link the library directly into your code, or dynamic linking to let your code use common DLL files.

Starting in Visual Studio 2015, the CRT has been refactored into new binaries. The Universal CRT (UCRT) contains the functions and globals exported by the standard C99 CRT library. The UCRT is now a Windows component, and ships as part of Windows 10. The static library, DLL import library, and header files for the UCRT are now found in the Windows 10 SDK. When you install Visual C++, Visual Studio setup installs the subset of the Windows 10 SDK required to use the UCRT. You can use the UCRT on any version of Windows supported by Visual Studio 2015 and later versions. You can redistribute it using vcredist for supported versions of Windows other than Windows 10. For more information, see Redistributing Visual C++ Files.

The following table lists the libraries that implement the UCRT.

 

Windows 下 C Runtime Library 其實是Microsoft對C standard library implement ,這樣呢,每一個程式就可以直接使用C標準庫裡面的函數了,而後來又出現了C++,所以C Runtime library 基礎上又開發了C++ Runtime Library ,實現對於C++標準庫的支持。

如果你有安裝VS的話,你可以去安裝的目錄( \VC\ct\src ),就有CRT的Source code,比如說裡面有C的stdio.h,也有C++的iostream。

 

在C Runtime Library出現之前,許多的程式啊都是用C去寫的,而且這些程式都要使用到標準的C Library,按照以前的方式,這些程式最後都需要COPY一份Standard library 的implement到程式中,這樣你想哦,你有這麼多之程式,然後每一之程式又有相同的東西( 每一個程式一份 ) ,這樣有沒有很熟悉............................。

 

沒錯 ! 所以微軟做了一件事情,就是把標準C庫做為動態連接來實現,這樣多個成是用C標準庫的時候,就不用大家都持有一份了。

 

 

2. MT, MTd, MD, MDd

 

C++ Standard Library

C++ Standard Library Characteristics Option Preprocessor directives
libcpmt.lib Multithreaded, static link /MT _MT
msvcprt.lib Multithreaded, dynamic link (import library for MSVCPversion.dll) /MD _MT, _DLL
libcpmtd.lib Multithreaded, static link /MTd _DEBUG, _MT
msvcprtd.lib Multithreaded, dynamic link (import library for MSVCPversionD.DLL) /MDd _DEBUG, _MT, _DLL

 

至於什麼是靜態的Library,什麼又是動態 ? 

在這裡先做一個簡單的解釋,之後如果有時間的話,我再寫第二篇 ( 寫到這裡已經第二天了 ..... 我怕我詳細寫下去,可能這禮拜搞不完這一篇 =____ = )

 

靜態庫

在連結的階段,會將編譯的目標文件.obj與引用道的庫.lib一起連接打包道可執行文件exe裡面去,程式運行的時候,就不再需要該靜態庫了。

也就是因為這樣,所以編譯出來的程式體積比較肥。

 

動態庫

在連結的階段,動態褲的dll並沒有真正被連接到目標代碼中,只是將這個動態庫的聲明連接到目標代碼中,這樣程式運行的時候才知道怎樣使用這個動態庫。

感覺就是,你可能在寫一個功能,而這個功能需要用到某一個library,於是你就用Loadlibrary的方式,將library Load進來,然後用完或得到資料後,在Free掉。

這有個好處,那就是最後得到的.exe體積就會比較小了。

 

 

 

Final :

我們知道作業系統一般是用 C 寫的(因為那時還沒有 C++C 已經算是最高級的電腦語言了),不管是 Linux/ Unix 還是 Windows 底層都是大量的 C 代碼。在開發作業系統及相應的應用程式時,很多的程式都會用到相同基礎功能的函式程式庫。為了方便開發就把經常用到的底層的基礎函數封閉成庫(不然你每寫一個程式都要把這基礎功能實現的原始程式碼拷貝一份到自己的工程,或自己再實現一次),於是就有了 C 運行時庫(C Runtime Library),也就是靜態程式庫 libc.lib(Release )libcd.lib(Debug )

因為早期的作業系統和程式都相應簡單,使用者的需求也不高,那時的作業系統還沒有多工、多執行緒的概念。所以 libc.liblibcd.lib 當然只能支援單執行緒的程式,而無法支援多執行緒的程式,因此這個運行時庫叫 Single-Threaded(/ML)的方式。

後來,隨著電腦的普及和發展,電腦要完成的任務越來越多,人們對時間和性能的要求也越來越高,為滿足這些需求,作業系統就有了多工的概念,也有了多執行緒的技術。而之前的運行時庫 libc.liblibcd.lib 只能用於單執行緒,已經無法滿足很多程式的需要,於是多執行緒的運行時庫也就應運而生,這就是 libcmt.liblibcmtd.lib,也就是/MT/MTd 的方式。

/MT/MTd 解決了多執行緒的問題,但隨著程式的越來越複雜,一個程式可能會用到多個其他程式的庫,多個程式可能會用到相同的庫,在記憶體中會保存多份的相同的靜態程式庫。假設 A 程式使用了 C.libB 程式也使用了 C.libAB 程式同時運行時,在記憶體中就會同時存在兩份 C.lib

​​​​​​​

 

 

 

 

 

 

 

 

 

 

 

 

 

 

arrow
arrow
    全站熱搜

    Eric 發表在 痞客邦 留言(0) 人氣()