Runtime: When a program is running, or executing, it is said to be in runtime. The term is mostly used by software developers to specify when errors in a program occur. A "runtime error" is an error that happens while the program is executing. For example if a program told you that 2 + 2 was 5000 that would be a runtime error. A memory leak where the program sucks up excessive amounts of system memory is also a runtime error. The other major type of program error is a compile-time error where the application will not even compile into an executable program. Examples of compile-time errors are syntax errors in the program code and file linking errors.
http://dev.cbw.com/c/c/2005965601_4211746.shtml
執行階段程式庫是程式在運行時所需要的庫檔案,通常執行階段程式庫是以LIB或DLL形式提供的。C執行階段程式庫誕生於20世紀70年代,當時的程式世界還很單純,應用程式都是單線程的,多任務或多線程機制在此時還屬於新觀念。所以這個時期的C執行階段程式庫都是單線程的。
隨著作業系統多線程技術的發展,最初的C執行階段程式庫無法滿足程式的需求,出現了嚴重的問題。C執行階段程式庫使用了多個全域變數(例如errno)和靜態變數,這可能在多線程程式中引起衝突。假設兩個線程都同時設定errno,其結果是後設定的errno會將先前的覆蓋,使用者得不到正確的錯誤資訊。
因此,Visual C++提供了兩種版本的C執行階段程式庫。一個版本供單線程應用程式調用,另一個版本供多線程應用程式調用。多線程執行階段程式庫與單線程執行階段程式庫有兩個重大差別:
(1)類似errno的全域變數,每個線程單獨設定一個;
這樣從每個線程中可以擷取正確的錯誤資訊。
(2)多線程庫中的資料結構以同步機制加以保護。
這樣可以避免訪問時候的衝突。
Visual C++提供的多線程執行階段程式庫又分為靜態連結庫和動態連結程式庫兩類,而每一類執行階段程式庫又可再分為debug版和release版,因此Visual C++共提供了6個執行階段程式庫。如下表:
| C執行階段程式庫 |
庫檔案 |
| Single thread(static link) |
libc.lib |
| Debug single thread(static link) |
libcd.lib |
| MultiThread(static link) |
libcmt.lib |
| Debug multiThread(static link) |
libcmtd.lib |
| MultiThread(dynamic link) |
msvert.lib |
| Debug multiThread(dynamic link) |
msvertd.lib |
2.C執行階段程式庫的作用
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++,並在重裝在時選中安裝運行庫原始碼選項。
3.各種C執行階段程式庫的區別
(1)靜態連結的單線程庫
靜態連結的單線程庫只能用於單線程的應用程式,C執行階段程式庫的目標代碼最終被編譯在應用程式的二進位檔案中。通過/ML編譯選項可以設定Visual C++使用靜態連結的單線程庫。
(2)靜態連結的多線程庫
靜態連結的多線程庫的目標代碼也最終被編譯在應用程式的二進位檔案中,但是它可以在多線程程式中使用。通過/MD編譯選項可以設定Visual C++使用靜態連結的單線程庫。
(3)動態連結的執行階段程式庫
動態連結的執行階段程式庫將所有的C庫函數儲存在一個單獨的動態連結程式庫MSVCRTxx.DLL中,MSVCRTxx.DLL處理了多線程問題。使用/ML編譯選項可以設定Visual C++使用動態連結的執行階段程式庫。
/MDd、 /MLd 或 /MTd 選項使用 Debug runtime library(調試版本的運行時刻函數庫),與/MD、 /ML 或 /MT分別對應。Debug版本的 Runtime Library 包含了調試資訊,並採用了一些保護機制以協助發現錯誤,加強了對錯誤的檢測,因此在運行效能方面比不上Release版本。
下面看一個未正確使用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裡修改編譯選項即可。
***********************************************
http://dev.cbw.com/c/c/2005965601_4211746.shtml
C執行階段程式庫在VC下是指實現了標準C介面的函數庫 有靜態庫,也有動態庫 包括三個檔案LIBC.LIB,LIBCMT.LIB,MSVCRT.LIB 具體包括了使用了哪個庫要看你在編譯時間候的選項 具體見下表: C Run-Time Library 特點 編譯選項 宏定義 (without iostream) LIBC.LIB Single threaded, static link /ML LIBCMT.LIB Multithreaded, static link /MT _MT MSVCRT.LIB Multithreaded, dynamic link /MD _MT,_DLL (import library for MSVCRT.DLL) |
|
|
|
從字面上看,運行庫是程式在運行時所需要的庫檔案。通常運行庫是以DLL形式提供的。Delphi和C++ Builder的運行庫為.bpl檔案,實際還是一個DLL。運行庫中一般包括編程時常用的函數,如字串操作、檔案操作、介面等內容。不同的語言所支援的函數通常是不同的,所以使用的庫也是完全不同的,這就是為什麼有VB運行庫、C運行庫、Delphi運行庫之分的原因。即使都是C++語言,也可能因為提供的函數不同,而使用不同的庫。如VC++使用的運行庫和C++ Builder就完全不同。 如果不使用運行庫,每個程式中都會包括很多重複的代碼,而使用運行庫,可以大大縮小編譯後的程式的大小。但另一方面,由於使用了運行庫,所以在分發程式時就必須帶有這些庫,比較麻煩。如果在作業系統中找不到相應的運行庫程式就無法運行。為瞭解決這個矛盾,Windows總是會帶上它自己開發的軟體的最新的運行庫。象Windows 2000以後的版本都包括Visual Basic 5.0/6.0的庫。Internet Explorer總是帶有最新的Visual C++ 6.0的庫。Windows XP帶有Microsoft .NET 1.0(用於VB.NET和C#)的庫。Visual C++、Delphi和C++ Builder允許使用者選擇所編譯得到的程式是否依賴於運行庫。而VB、FoxPro、PowerBuilder、LabWindows/CVI和Matlab就不允許使用者進行這種選擇,必須依賴於運行庫。 |