C RunTime Library 暨 深入理解編譯選項的含義 – 01

來源:互聯網
上載者:User
以下內容來源於網路,作者不明。轉自:http://advancedcj.wordpress.com/2010/06/18/c-runtime-library-1/  

一 產生

 執行階段程式庫是程式在運行時所需要的庫檔案,通常以LIB或DLL形式提供。 C執行階段程式庫就是C run-time library,誕生於20世紀70年代,是C而非C++語言世界的概念,C程式運行時需要這些庫中的函數。 C 語言是所謂的“小核心”語言,就其語言本身來說很小(不多的關鍵字,程式流程式控制制,資料類型等)。所以,C語言核心開發出來之後,Dennis Ritchie和Brian Kernighan就用C本身重寫了90%以上的UNIX系統函數,並且把其中最常用的部分獨立出來,形成標頭檔和對應的LIBRARY,C執行階段程式庫就是這樣形成的。 隨著C語言的流行,各個C編譯器的生產商/個體/團體都遵循老的傳統,在不同平台上都有相對應的Standard Library,但大部分實現都是與各個平台有關的。由於各個C編譯器對C的支援和理解有很多分歧和微妙的差別,所以就有了ANSI C;ANSI C(主觀意圖上)詳細的規定了C語言各個要素的具體含義和編譯器實現要求,引進了新的函式宣告方式,同時訂立了Standard Library的標準形式。所以C執行階段程式庫由編譯器生產商提供。至於由其他廠商/個人/團體提供的標頭檔和庫函數,應當稱為第三方C運行庫(Third party C run-time libraries)。 二 發展 到了 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 C運行庫剛誕生的時候,程式世界還很單純,應用程式都是單線程的,多任務或多線程機制在此時還屬於新觀念。所以這個時期的C執行階段程式庫都是單線程的。 隨著作業系統多線程技術的發展,最初的C執行階段程式庫無法滿足程式的需求,出現了嚴重的問題。C執行階段程式庫使用了多個全域變數(例如errno)和靜態變數,這可能在多線程程式中引起衝突。假設兩個線程都同時設定errno,其結果是後設定的errno會將先前的覆蓋,使用者得不到正確的錯誤資訊。 因此,Visual C++提供了兩種版本的C執行階段程式庫。一個版本供單線程應用程式調用,另一個版本供多線程應用程式調用。多線程執行階段程式庫與單線程執行階段程式庫有兩個重大差別: (1)類似errno的全域變數,每個線程單獨設定一個。這樣從每個線程中可以擷取正確的錯誤資訊。 (2)多線程庫中的資料結構以同步機制加以保護。     這樣可以避免訪問時候的衝突。 Visual C++提供的多線程執行階段程式庫又分為靜態連結庫和動態連結程式庫兩類,而每一類執行階段程式庫又可再分為debug版和release版,因此Visual C++共提供了6個執行階段程式庫。如下表:(單線程和多線程都有debug版和release版;只有多線程才有靜態連結庫和動態連結程式庫之分) C執行階段程式庫 庫檔案Single thread(static link) libc.libDebug single thread(static link) libcd.libMultiThread(static link) libcmt.libDebug multiThread(static link) libcmtd.libMultiThread(dynamic link) msvcrt.lib(匯入庫)Debug multiThread(dynamic link) msvcrtd.lib(匯入庫) 三 C運行庫的作用 (1)C執行階段程式庫包含了C程式啟動並執行最基本和最常用的函數(如memcpy、printf、malloc等)。(2)C執行階段程式庫除了給我們提供必要的庫函數調用之外,它提供的另一個最重要的功能是為應用程式添加啟動函數。C執行階段程式庫啟動函數的主要功能為進行程式的初始化,對全域變數進行賦初值,載入使用者程式的入口函數。 不採用寬字元集的控制台程式的進入點為mainCRTStartup(void)。下面我們以該函數為例來分析執行階段程式庫究竟為我們添加了怎樣的入口程式。這個函數在crt0.c中被定義,下列的代碼經過了筆者的整理和簡化: void mainCRTStartup(void)
{
int mainret;
/*獲得WIN32完整的版本資訊*/
_osver = GetVersion();
_winminor = (_osver >>  & 0x00FF ;
_winmajor = _osver & 0x00FF ;
_winver = (_winmajor <<  + _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語言執行階段程式庫和應用程式才能正常地工作起來。 你寫的程式可以沒有math庫,程式照樣運行,只是不能處理複雜的數學運算,不過如果沒有了C run-time庫,main()就不會被調用,exit()也不能被響應。 除了crt0.c外,C執行階段程式庫中還包含wcrt0.c、 wincrt0.c、wwincrt0.c三個檔案用來提供初始化函數。wcrt0.c是crt0.c的寬字元集版,wincrt0.c中包含windows應用程式的入口函數,而wwincrt0.c則是wincrt0.c的寬字元集版。 Visual C++的執行階段程式庫原始碼預設情況下不被安裝。如果您想查看其原始碼,則需要重裝Visual C++,並在重裝在時選中安裝運行庫原始碼選項。
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.