帶你玩轉Visual Studio——帶你跳出坑爹的Runtime Library坑

來源:互聯網
上載者:User

標籤:windows   error   already   程式   工程   

在Windows下進行C++的開發,不可避免的要與Windows的底層庫進行互動,然而VS下的一項設定MT、MTd、MD和MDd卻經常讓人搞迷糊,相信不少人都被他坑過,特別是你工程使用了很多第三庫的時候,及容易出現各種連結問題。看一下下面這個錯誤提示: 
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)

有多少人被這玩意坑過,被坑過的請舉腳!哈哈……

既然這裡這麼容易出問題,我們就有必要對其進行深入的瞭解,知其然且知其所以然才能萬事無懼!

1. 什麼是Runtime Library?

Runtime Library就是執行階段程式庫,也簡稱CRT(C Run Time Library)。是程式在運行時所需要的庫檔案,通常執行階段程式庫是以Lib或Dll形式提供的。

Windows下C Runtime Library是微軟對C標準庫函數的實現,這樣每個程式可以直接使用C標準庫的函數;後來出現了C++,於是又在C Runtime Library基礎上開發了C++ Runtime Library,實現了對C++標準庫的支援。因此現在Windows下的C/C++執行階段程式庫既包含子C標準庫,也包含了C++標準庫。如果你安裝了VS2010,在安裝目錄下的VC\crt\src下(如我的目錄是C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\crt\src)有執行階段程式庫(CRT)的原始碼,這裡既有C的檔案(如output.c、stdio.h等),也有C++的檔案(如iostream、string)。

在C Runtime Library出現之前,許多程式都使用C編寫,而這些程式都要使用標準的C庫,按照以前的方式每一個程式最終都要拷貝一份標準庫的實現到程式中,這樣同一時刻記憶體中可能有許多份標準庫的代碼(一個程式一份),所以微軟出於效率的考慮把標準C庫做為動態連結來實現,這樣多個程式使用C標準庫時記憶體中就只有一份拷貝了。

確切地說執行階段程式庫指的就是對這些底層的基礎功能實現的動態庫(Dll),執行階段程式庫和普通的Dll一樣,只有程式用到了它才會被載入,沒有程式使用的時候不會駐留記憶體的。話雖如此,但有多少系統的東西說不定也是用C寫的,這些東西的存在就使C執行階段程式庫存在於記憶體中了,所以執行階段程式庫幾乎總是需要的。雖然說執行階段程式庫應該是動態庫,但習慣上我們把與動態執行階段程式庫相同代碼編譯出來的靜態庫也稱為執行階段程式庫,因此VC++下的執行階段程式庫有ML、MLd、MT、MTd、MD、MD六種(這個後面會講)。

1.1 執行階段程式庫的主要作用
  1. 提供C標準庫(如memcpy、printf、malloc等)、C++標準庫(STL)的支援。

  2. 應用程式添加啟動函數,啟動函數的主要功能為將要進行的程式初始化,對全域變數進行賦初值,載入使用者程式的入口函數。

不採用寬字元集的控制台程式的進入點為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 );}123456789101112131415161718192021

從以上代碼可知,運行庫在調用使用者程式的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的寬字元集版。

http://www.gexing.com/tupian/t/%E9%85%92%E6%B3%89%E5%B8%82%E5%A4%A7%E5%9C%A3%E5%B9%B3%E5%8F%B0QQ82933700/good/

http://www.gexing.com/tupian/t/%E6%A1%93%E5%8F%B0%E5%8E%BF%E5%A4%A7%E5%9C%A3%E5%B9%B3%E5%8F%B0QQ82933700

http://www.gexing.com/tupian/t/%E6%97%A0%E9%94%A1%E5%B8%82%E5%A4%A7%E5%9C%A3%E6%8B%9B%E5%95%86QQ82933700/good/

http://www.gexing.com/tupian/t/%E5%95%86%E4%B8%98%E5%B8%82%E5%A4%A7%E5%9C%A3%E6%80%BB%E4%BB%A3QQ82933700

http://www.gexing.com/tupian/t/%E5%A4%A9%E5%BF%83%E5%8C%BA%E5%A4%A7%E5%9C%A3%E6%80%BB%E4%BB%A3QQ82933700/good/

http://www.gexing.com/tupian/t/%E7%8E%89%E6%BA%AA%E5%B8%82%E5%A4%A7%E5%9C%A3%E6%8B%9B%E5%95%86QQ82933700

http://www.gexing.com/tupian/t/%E6%B9%98%E6%BD%AD%E5%B8%82%E5%A4%A7%E5%9C%A3%E6%8B%9B%E5%95%86QQ82933700

http://www.gexing.com/tupian/t/%E6%B4%9B%E5%AE%81%E5%8E%BF%E5%A4%A7%E5%9C%A3%E6%8B%9B%E5%95%86QQ82933700/good/

http://www.gexing.com/tupian/t/%E5%9B%9B%E4%BC%9A%E5%B8%82%E5%A4%A7%E5%9C%A3%E5%B9%B3%E5%8F%B0QQ82933700

http://www.gexing.com/tupian/t/%E9%98%B3%E8%B0%B7%E5%8E%BF%E5%A4%A7%E5%9C%A3%E5%BD%A9%E7%A5%A8QQ82933700/good/

http://www.gexing.com/tupian/t/%E9%82%95%E5%AE%81%E5%8C%BA%E5%A4%A7%E5%9C%A3%E6%8B%9B%E5%95%86QQ82933700/good/

http://www.gexing.com/tupian/t/%E5%8C%97%E5%85%B3%E5%8C%BA%E5%A4%A7%E5%9C%A3%E5%BD%A9%E7%A5%A8QQ82933700

http://www.gexing.com/tupian/t/%E6%B8%85%E6%B2%B3%E5%8C%BA%E5%A4%A7%E5%9C%A3%E5%BD%A9%E7%A5%A8QQ82933700/good/

http://www.gexing.com/tupian/t/%E5%85%B4%E5%AE%BE%E5%8C%BA%E5%A4%A7%E5%9C%A3%E5%A8%B1%E4%B9%90QQ82933700

http://www.gexing.com/tupian/t/%E5%AE%9C%E6%98%8C%E5%B8%82%E5%A4%A7%E5%9C%A3%E5%BD%A9%E7%A5%A8QQ82933700/good/

http://www.gexing.com/tupian/t/%E9%BC%93%E6%A5%BC%E5%8C%BA%E5%A4%A7%E5%9C%A3%E5%BD%A9%E7%A5%A8QQ82933700

http://www.gexing.com/tupian/t/%E5%90%AB%E5%B1%B1%E5%8E%BF%E5%A4%A7%E5%9C%A3%E5%A8%B1%E4%B9%90QQ82933700/good/

http://www.gexing.com/tupian/t/%E5%AE%89%E5%AE%9A%E5%8C%BA%E5%A4%A7%E5%9C%A3%E6%80%BB%E4%BB%A3QQ82933700

http://www.gexing.com/tupian/t/%E4%BA%A4%E5%9F%8E%E5%8E%BF%E5%A4%A7%E5%9C%A3%E5%B9%B3%E5%8F%B0QQ82933700/good/

http://www.gexing.com/tupian/t/%E4%B8%9C%E8%BE%BD%E5%8E%BF%E5%A4%A7%E5%9C%A3%E6%80%BB%E4%BB%A3QQ82933700

http://www.gexing.com/tupian/t/%E9%9D%92%E5%8E%9F%E5%8C%BA%E5%A4%A7%E5%9C%A3%E5%B9%B3%E5%8F%B0QQ82933700/good/


帶你玩轉Visual Studio——帶你跳出坑爹的Runtime Library坑

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.