1. 程式人生 > >C執行時庫(C Run-time Library)詳解

C執行時庫(C Run-time Library)詳解


一、什麼是C執行時庫

1)C執行時庫就是 C run-time library,是 C 而非 C++ 語言世界的概念:取這個名字就是因為你的 C 程式執行時需要這些庫中的函式.

2)C 語言是所謂的“小核心”語言,就其語言本身來說很小(不多的關鍵字,程式流程控制,資料型別等);所以,C 語言核心開發出來之後,Dennis Ritchie 和 Brian Kernighan 就用 C 本身重寫了 90% 以上的 UNIX 系統函式,並且把其中最常用的部分獨立出來,形成標頭檔案和對應的 LIBRARY,C run-time library 就是這樣形成的。

3)隨後,隨著 C 語言的流行,各個 C 編譯器的生產商/個體/團體都遵循老的傳統,在不同平臺上都有相對應的 Standard Library,但大部分實現都是與各個平臺有關的。由於各個 C 編譯器對 C 的支援和理解有很多分歧和微妙的差別,所以就有了 ANSI C;ANSI C (主觀意圖上)詳細的規定了 C 語言各個要素的具體含義和編譯器實現要求,引進了新的函式宣告方式,同時訂立了 Standard Library 的標準形式。所以C執行時庫由編譯器生產商提供。至於由其他廠商/個人/團體提供的標頭檔案和庫函式,應當稱為第三方 C 執行庫(Third party C run-time libraries)。

4)C run-time library裡面含有初始化程式碼,還有錯誤處理程式碼(例如divide by zero處理)。你寫的程式可以沒有math庫,程式照樣執行,只是不能處理複雜的數學運算,不過如果沒有了C run-time庫,main()就不會被呼叫,exit()也不能被響應。因為C run-time library包含了C程式執行的最基本和最常用的函式。

5)到了 C++ 世界裡,有另外一個概念:Standard C++ Library,它包括了上面所說的 C run-time library 和 STL。包含 C run-time library 的原因很明顯,C++ 是 C 的超集,沒有理由再重新來一個 C++ run-time library. VC針對C++ 加入的Standard C++ Library主要包括:LIBCP.LIB, LIBCPMT.LIB和 MSVCPRT.LIB

二、Visual C++中對執行時庫的支援 

        執行時庫是程式在執行時所需要的庫檔案,通常執行時庫是以LIB或DLL形式提供的。C執行時庫誕生於20世紀70年代,當時的程式世界還很單純,應用程式都是單執行緒的,多工或多執行緒機制在此時還屬於新觀念。所以這個時期的C執行時庫都是單執行緒的。

  隨著作業系統多執行緒技術的發展,最初的C執行時庫無法滿足程式的需求,出現了嚴重的問題。C執行時庫使用了多個全域性變數(例如errno)和靜態變數,這可能在多執行緒程式中引起衝突。假設兩個執行緒都同時設定errno,其結果是後設置的errno會將先前的覆蓋,使用者得不到正確的錯誤資訊。

  因此,Visual C++提供了兩種版本的C執行時庫。一個版本供單執行緒應用程式呼叫,另一個版本供多執行緒應用程式呼叫。多執行緒執行時庫與單執行緒執行時庫有兩個重大差別:

  (1)類似errno的全域性變數,每個執行緒單獨設定一個;

  這樣從每個執行緒中可以獲取正確的錯誤資訊。

  (2)多執行緒庫中的資料結構以同步機制加以保護。

  這樣可以避免訪問時候的衝突。

  Visual C++提供的多執行緒執行時庫又分為靜態連結庫和動態連結庫兩類,而每一類執行時庫又可再分為debug版和release版,因此Visual C++共提供了6個執行時庫。如下表:

Reusable LibrarySwitchLibraryMacro(s) Defined
Single Threaded/MLLIBC(none)
Static MultiThread/MTLIBCMT_MT
Dynamic Link (DLL)/MDMSVCRT_MT and _DLL
Debug Single Threaded/MLdLIBCD_DEBUG
Debug Static MultiThread/MTdLIBCMTD_DEBUG and _MT
Debug Dynamic Link (DLL)/MDdMSVCRTD_DEBUG, _MT, and _DLL
注:從Visual C++ 2005開始,libcp.lib和libcpd.lib(老的/ML和/MLd選項)已經被移除。通過/MT和/MTd使用libcpmt.lib和libcpmtd.lib取代。

   /MT和/MTd表示採用多執行緒CRT庫的靜態lib版本。該選項會在編譯時將執行時庫以靜態lib的形式完全嵌入。該選項生成的可執行檔案執行時不需要執行時庫dll的參加,會獲得輕微的效能提升,但最終生成的二進位制程式碼因鏈入龐大的執行時庫實現而變得非常臃腫。當某專案以靜態連結庫的形式嵌入到多個專案,則可能造成執行時庫的記憶體管理有多份,最終將導致致命的“Invalid Address specified to RtlValidateHeap”問題。另外託管C++和CLI中不再支援/MT和/MTd選項。

    /MD和/MDd表示採用多執行緒CRT庫的動態dll版本,會使應用程式使用執行時庫特定版本的多執行緒DLL。連結時將按照傳統VC連結dll的方式將執行時庫MSVCRxx.DLL的匯入庫MSVCRT.lib連結,在執行時要求安裝了相應版本的VC執行時庫可再發行元件包(當然把這些執行時庫dll放在應用程式目錄下也是可以的)。 因/MD和/MDd方式不會將執行時庫連結到可執行檔案內部,可有效減少可執行檔案尺寸。當多專案以MD方式運作時,其內部會採用同一個堆,記憶體管理將被簡化,跨模組記憶體管理問題也能得到緩解。

三、MSND上相關說明

MSDN上對執行時庫的相關說明

選項         

說明

/MD

使應用程式使用執行庫的多執行緒並特定於 DLL 的版本。 定義 _MT 和 _DLL,並使編譯器將庫名 MSVCRT.lib 放入 .obj 檔案中。

用此選項編譯的應用程式靜態連結到 MSVCRT.lib。 此庫提供允許連結器解析外部引用的程式碼的層。 實際工作程式碼包含在 MSVCR100.DLL, 中,該庫必須在執行時對於與 MSVCRT.lib 連結的應用程式可用。

/MDd

定義 _DEBUG_MT 和 _DLL,並使應用程式使用執行庫的除錯多執行緒並特定於 DLL 的版本。 它還使編譯器將庫名 MSVCRTD.lib 放入 .obj 檔案中。

/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 的應用程式。

將  解釋為命名 DLL 而不是 .exe 檔案;預設程式名成為基名稱.dll 而不是基名稱.exe。

除非顯式指定 /MD,否則將暗指 /MT

/LDd

建立除錯 DLL。 定義 _MT 和 _DEBUG

MSDN上的警告
不要混合使用執行時庫的靜態版本和動態版本。在一個程序中有多個執行時庫副本會導致問題,因為副本中的靜態資料不與其他副本共享。連結器禁止在 .exe 檔案內部既使用靜態版本又使用動態版本連結,但您仍可以使用執行時庫的兩個(或更多)副本。例如,當與用動態 (DLL) 版本的執行時庫連結的 .exe 檔案一起使用時,用靜態(非 DLL)版本的執行時庫連結的動態連結庫可能導致問題。(還應該避免在一個程序中混合使用這些庫的除錯版本和非除錯版本)。

四、舉例

  C執行時庫除了給我們提供必要的庫函式呼叫(如memcpy、printf、malloc等)之外,它提供的另一個最重要的功能是為應用程式新增啟動函式
  C執行時庫啟動函式的主要功能為進行程式的初始化,對全域性變數進行賦初值,載入使用者程式的入口函式
  不採用寬字符集的控制檯程式的入口點為mainCRTStartup(void)。下面我們以該函式為例來分析執行時庫究竟為我們添加了怎樣的入口程式。這個函式在crt0.c中被定義:

void mainCRTStartup(void)
{
 int mainret;
 /*獲得WIN32完整的版本資訊*/
 _osver = GetVersion();
 _winminor = (_osver >> 8) & 0x00FF ;
 _winmajor = _osver & 0x00FF ;
 _winver = (_winmajor << 8) + _winminor;
 _osver = (_osver >> 16) & 0x00FFFF ;

 _ioinit(); /* initialize lowio */

 /* 獲得命令列資訊 */
 _acmdln = (char *) GetCommandLineA();

 /* 獲得環境資訊 */
 _aenvptr = (char *) __crtGetEnvironmentStringsA();

 _setargv(); /* 設定命令列引數 */
 _setenvp(); /* 設定環境引數 */

 _cinit(); /* C資料初始化:全域性變數初始化,就在這裡!*/

 __initenv = _environ;
 mainret = main( __argc, __argv, _environ ); /*呼叫main函式*/

 exit( mainret );
}

 從以上程式碼可知,執行庫在呼叫使用者程式的main或WinMain函式之前,進行了一些初始化工作。初始化完成後,接著才呼叫了我們編寫的main或WinMain函式。只有這樣,我們的C語言執行時庫和應用程式才能正常地工作起來。 

  除了crt0.c外,C執行時庫中還包含wcrt0.c、 wincrt0.c、wwincrt0.c三個檔案用來提供初始化函式。wcrt0.c是crt0.c的寬字符集版,wincrt0.c中包含windows應用程式的入口函式,而wwincrt0.c則是wincrt0.c的寬字符集版。

  Visual C++的執行時庫原始碼預設情況下不被安裝。如果您想檢視其原始碼,則需要重灌Visual C++,並在重灌在時選中安裝執行庫原始碼選項。

下面看一個未正確使用C執行時庫的控制檯程式:

#include <stdio.h>
#include <afx.h>
int main()
{
 CFile file;
 CString str("I love you");
 TRY
 {
  file.Open("file.dat",CFile::modeWrite | CFile::modeCreate);
 }
 CATCH( CFileException, e )
 {
  #ifdef _DEBUG
  afxDump << "File could not be opened " << e->m_cause << "\n";
  #endif
 }
 END_CATCH

 file.Write(str,str.GetLength());
 file.Close();
}

在"rebuild all"的時候發生了link錯誤:
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex
main.exe : fatal error LNK1120: 2 unresolved externals
Error executing cl.exe.

    發生錯誤的原因在於Visual C++對控制檯程式預設使用單執行緒的靜態連結庫,而MFC中的CFile類已暗藏了多執行緒。我們只需要在Visual C++6.0中依次點選Project->Settings->C/C++選單和選項,在Project Options裡修改編譯選項即可。

相關推薦

C執行C Run-time Library

一、什麼是C執行時庫1)C執行時庫就是 C run-time library,是 C 而非 C++ 語言世界的概念:取這個名字就是因為你的 C 程式執行時需要這些庫中的函式.2)C 語言是所謂的“小核心”語言,就其語言本身來說很小(不多的關鍵字,程式流程控制,資料型別等);所以,C 語言核心開發出來之後,De

C執行Visual C++ C RunTime Lib

CRT 全稱:Visual C++ C RunTime Lib 就是C執行時庫。 注: 以下內容部分引自CSDN中相關討論的帖子,並結合自己的理解整理而成。僅供參考。 1)執行時庫就是 C run-time library,是 C 而非 C++ 語言世界的概念:取這個

如何理解C run-time libraryC執行)

 )執行時庫就是 C run-time library,是 C 而非 C++ 語言世界的概念:取這個名字就是因為你的 C 程式執行時需要這些庫中的函式. 2)C 語言是所謂的“小核心”語言,就其語言本身來說很小(不多的關鍵字,程式流程控制,資料型別等);所以,C 語言核心開發

CRTC Runtime Library—— C/C++執行

C runtime library(part of the C standard library) 任何一個 C 程式,它的背後都有一套龐大的程式碼來進行支撐,使得該程式得以執行在更高級別上,而不必擔心同計算機底層操作的細節,這套程式碼至少包括:

C/C++執行到底在Windows中起什麼作用猜想

以下是作者的一些猜想: 1. 我們在用VC程式設計時,會在執行我們的main函式前,系統先通過Kernel32呼叫一些函式,執行一些C的初始化準備工作,我們一般叫C執行時庫的初始化。那麼這些初始化的作用是什麼?是否是必要的?不知道大家有沒有思考過這個問題。 以下是我對這

[轉]CC++執行

轉自csdn原文:https://blog.csdn.net/ithzhang/article/details/20160009 圖片請去原文檢視 在使用VC構建專案時,經常會遇到下面的連結錯誤:   初學者面對這些錯誤常常不知所錯:libcmt.lib是什麼東西?msvcrtd.dll又是幹嗎用的?在

什麼是c執行

nafxcw.lib 和 libcmt.lib衝突問題。 解決辦法: 屬性設定裡讓程式先找到nafxcw.lib. 解決辦法參考:https://www.cnblogs.com/suiyingjie/archive/2012/10/29/2745031.html 從vs2008 工程

終於理解了什麼是c/c++執行,以及libcmt msvcrt等內容

在各個版本的編譯器中,我們可以通過配置選項來設定程式使用的C和C++執行時庫的型別。如下圖(其他版本編譯器大同小異):MT選項:連結LIB版的C和C++執行庫。在連結時就會在將C和C++執行時庫整合到程式中成為程式中的程式碼,程式體積會變大。 MTd選項:LIB的除錯版。 M

C++小知識——C/C++執行外部程式呼叫外部exe程式

轉載自:https://blog.csdn.net/dongpanshan/article/details/7835722,其中我只用到了ShellExecute函式,根據下面的示例以及介紹的其中的引數進行了調整,實現了對外部exe的呼叫 C中的函式: 1.exec()

VS的執行Runtime lIB

在開發window程式是經常會遇到編譯好好的程式拿到另一臺機器上面無法執行的情況,這一般是由於另一臺機器上面沒有安裝響應的執行時庫導致的,那麼這個與編譯選項MT、MTd、MD、MDd有什麼關係呢?這是msdn上面的解釋: MT:mutithread,多執行緒庫

C++11 shared_ptr智能指針

space 詳解 .net 註意 變量 turn int 出錯 構造 要確保用 new 動態分配的內存空間在程序的各條執行路徑都能被釋放是一件麻煩的事情。C++ 11 模板庫的 <memory> 頭文件中定義的智能指針,即 shared _ptr 模板,就是用來

Android開發中屬性動畫ObjectAnimator中 插值器Time Interpolator

在 Android開發中,為了保持良好的互動體驗,我們經常會用到動畫來提升使用者體驗,而動畫中屬性動畫用的最多。 雖然動畫可以讓介面看起來不是那麼粗糙,但是很多時候僅僅只是勻速運動的動畫可能不足以描述一些我們想呈現給使用者的介面,比如模擬一個下落的小球,我們知道下落的小球並不是以勻速運動的,

C++細節 深拷貝和淺拷貝(位拷貝

前提 在物件拷貝過程中,如果沒有自定義拷貝建構函式,系統會提供一個預設的拷貝建構函式,預設的拷貝建構函式對於基本型別的成員變數,按位元組複製,對於類型別成員變數,呼叫其相應型別的拷貝建構函式。 閱讀《高質量的c c++程式設計》,第9章有這樣一段話,類似的話在《c++pr

Spring框架——AOP面向切面編程

通過 cts ssi 沒有 object 引入 集中 method 可能 1 AOP概述 ●AOP(Aspect-Oriented Programming,面向切面編程):是一種新的方法論,是對傳統 OOP(Object-Oriented Programming,面向對象

Web 安全之內容安全策略Content-Security-Policy,CSP

pid eba elf safe 數據 信息 java php 我們 1.CSP 簡介 內容安全策略(Content Security Policy,簡稱CSP)是一種以可信白名單作機制,來限制網站是否可以包含某些來源內容,緩解廣泛的內容註入漏洞,比如 XSS。 簡單來說,

linux netstat tcp全連線半連線

功能介紹(參考 LINUX MAN命令 大家可以自己去看一下 這裡只是列出常用的部分說明) 顯示網路連線狀態(如:LISTEN、ESTABLISHED、TIME_WAIT),路由地址,應用使用協議(如:TCP、UDP),IP和埠使用情況等其他網路資訊。 常用引數 –rou

linux netstat、tcp全連線半連線

參考 LINUX MAN命令 大家可以自己去看一下 這裡只是列出常用的部分說明 功能介紹 顯示網路連線狀態(如:LISTEN、ESTABLISHED、TIME_WAIT),路由地址,應用使用協議(如:TCP、UDP),IP和埠使用情況等其他網路

OpenCV contrib 3.2.0擴充套件模組新增與編譯VS2017+OpenCV3.2.0與排坑

一Cmake配置與生成 安裝cmake下載地址:https://cmake.org/download/ 獲取最新版本:cmake-3.8.1-win64-x64.msi(可執行程式,不是壓縮包) 下載完畢直接執行安裝,只有一個步驟要注意, 選擇‘addCmake t

【視覺-立體視覺】全域性匹配演算法SGBM實現含動態規劃DP

最近一直在學習SGBM演算法,作為一種全域性匹配演算法,立體匹配的效果明顯好於區域性匹配演算法,但是同時複雜度上也要遠遠大於區域性匹配演算法。演算法主要是參考Stereo Processing by Semiglobal Matching and Mutual Informa

Open vSwitch開放虛擬交換標準

  從虛擬機器到虛擬交換   提到虛擬化,大家第一印象往往是虛擬機器(Virtual Machine),VMware、Virtualbox,這些大名鼎鼎的虛擬機器軟體不少人都耳熟能詳。對企業使用者來說,虛擬技術最直接的好處是通過靈活配置資源、程式來高資源的利用率,從而降低應用成本。近些年,隨著虛擬化技術