/MT、/MD編譯選項,以及可能引起在不同堆中申請、釋放記憶體的問題

來源:互聯網
上載者:User

 

一、MD(d)、MT(d)編譯選項的區別1、編譯選項的位置

以VS2005為例,這樣子開啟:

1)         開啟項目的Property Pages對話方塊

2)         點擊左側C/C++節

3)         點擊Code Generation節

4)         右側第六行Runtime Library項目

2、各個設定選項代表的含義

編譯選項

包含

靜態連結的lib

說明

/MD

_MT、_DLL

MSVCRT.lib

多線程、Release、DLL版本的執行階段程式庫

/MDd

_DEBUG、_MT、_DLL

MSVCRTD.lib

多線程、Debug、DLL版本的執行階段程式庫

/MT

_MT

LIBCMT.lib

多線程、Release版本的執行階段程式庫

/MTd

_DEBUG、_MT

LIBCMTD.lib

多線程、Debug版本的執行階段程式庫

 

簡單的說:

(1)/MD,表示執行階段程式庫由作業系統提供一個DLL,程式裡不整合。

(2)/MT,表示執行階段程式庫由程式整合。

 

二、/MD、/MT的選擇      1、為什麼選擇/MD,不選/MT?

         (1)程式就不需要靜態連結執行階段程式庫,可以減小軟體的大小;

         (2)所有的模組都採用/MD,使用的是同一個堆,不存在A堆申請,B堆釋放的問題。

      2、為什麼選擇/MT,不選擇/MD?

         (1)有些系統可能沒有程式所需要版本的執行階段程式庫,程式必須把執行階段程式庫靜態連結上。

     (2)減少模組對外界的依賴。

      3、多個模組,必須選擇相同的執行階段程式庫。三、選擇/MT需要解決的堆空間釋放問題

         不同的模組各自有一份C執行階段程式庫代碼、或者根本沒有C執行階段程式庫,導致了各個模組會有各自的堆。如果在A堆中申請空間,到B堆中釋放就會有崩潰,在模組A申請的空間,必須在模組A中釋放。

         附錄的DLL以及DLLUser代碼,以STL的string為例,通過修改編譯選項驗證了這個問題。string在賦值的時候需要釋放掉原來的記憶體空間,然後再申請新的記憶體空間儲存新的內容,如果跨模組了,釋放的時候就存在“A模組申請B模組釋放”的問題,導致程式崩潰。

   (跨模組釋放記憶體導致崩潰的內容,在《windows核心編程》第五版Page511談DLL和進程的地址空間時有談到)

四、選擇/MD需要注意多個模組使用不同版本執行階段程式庫的問題

     (2012-9-17補充)

     多個dll被一個exe LoadLibrary載入,如果這些dll使用的執行階段程式庫是不同的,那麼可能出現載入失敗,原因可能是舊版本的執行階段程式庫已經在了,而某個dll它需要的是新版本的執行階段程式庫,舊版本不符合要求。

     如果工程裡所有的模組都是自己寫的或者可以完全控制的,那麼這個問題不難解決,只需要在工程設定裡都設定/MD,然後在相同的環境下編譯一次就行。但是假如這個模組是外界提供的呢?

     可能存在這種情況:A動態庫使用了B靜態庫,B靜態庫使用了C動態庫,B靜態庫是外界提供的,我們要使用它,但無法修改它,我們也無法接觸到C動態庫。如果C動態庫使用的執行階段程式庫版本跟編譯A動態庫的本地使用的不一致,那麼A動態庫裡的嵌入資訊就會記錄兩個不同版本的執行階段程式庫,它被載入的時候,可能會選擇版本新的。假設A動態庫被一個exe LoadLibrary載入,而這個exe本身的執行階段程式庫是舊的,這樣就會導致A動態庫載入失敗,即便把新的執行階段程式庫拷貝到目錄下也不行,因為exe這個進程已經載入了那箇舊的執行階段程式庫。這時候必須使用manifest檔案指定嵌入到A動態庫裡的執行階段程式庫為某個版本,忽略掉C動態庫使用的執行階段程式庫版本。

     這個問題挺複雜的,我心思沒去驗證windows的PE檔案載入會對執行階段程式庫做什麼樣的優先選擇、執行階段程式庫在靜態庫裡的記錄…。只要記住,給外界使用的組件版本盡量避免使用/MD(這樣會導致膨脹嗎?據說,安裝包可以做位元組流式壓縮)。

  附上另一個問題:靜態庫的依賴關係:exe-->libA-->libB,現在不想讓exe接觸到libB,於是把libA的librarian選項-->General選項-->Link Library Dependencies設定為Yes,這樣即可,libA會包含libB,exe只需要接觸libA。另外需要特別注意,libA對libB的依賴只需要且只能在Solution的Project Dependencies裡設定,如果在libA的代碼裡寫了”#pragma comment(lib, "libB.lib")”,會導致exe在link libA的時候提示找不到libA。如果exe還出現link錯誤,那一定是VS抽筋了:)(2013.5.30補充)

四、參考資料

1、微軟關於MT、MD等的詳細介紹

http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=VS.71).aspx

2、不要出現A模組申請,B模組釋放的情況

http://www.cnblogs.com/minggoddess/archive/2010/12/15/1907179.html

3、執行階段程式庫有哪些版本

http://www.cppblog.com/MichaelLiu/articles/10607.html

4、CSDN上關於堆空間釋放的討論

http://topic.csdn.net/t/20010112/09/57983.html

http://topic.csdn.net/t/20031009/17/2338051.html

http://topic.csdn.net/u/20090502/00/bf1602e3-ddf5-49b0-af81-8a23383f9ddc.html

http://blog.csdn.net/blz_wowar/article/details/2176536

5、不同模組不同的堆

http://www.cnblogs.com/WengYB/archive/2011/08/18/2144727.html

 

6、因為執行階段程式庫版本問題導致載入失敗的分享

http://blog.csdn.net/dev_yarin/article/details/6768373

http://blog.163.com/henan_lujun/blog/static/19538333200611485511640/

 7、《windows核心編程》

附錄:

:http://files.cnblogs.com/cswuyg/Test_MD_and_MT.rar

 

聯繫我們

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