在開發window程序是經常會遇到編譯好好的程序拿到另一台機器上面無法運行的情況,這一般是由於另一台機器上面沒有安裝響應的運行時庫導致的,那么這個與編譯選項MT、MTd、MD、MDd有什么關系呢?這是msdn上面的解釋:
MT:mutithread,多線程庫,編譯器會從運行時庫里面選擇多線程靜態連接庫來解釋程序中的代碼,即連接LIBCMT.lib庫
MTd:mutithread+debug,多線程調試版,連接LIBMITD.lib庫
MD:MT+DLL,多線程動態庫,連接MSVCRT.lib庫,這是個導入庫,對應動態庫為MSVCRT.dll
MDd: MT+DLL+debug,多線程動態調試庫,連接MSVCRTD.lib庫,對應動態庫為MSVCRTD.dll
開發多線程程序時(單線程本文不做討論),需要選擇MT、MTd、MD、MDd其中的一個。
對於MT/MTd,由於連接運行時庫是LIBCMT.lib/LIBCMTD.lib,這兩個庫是靜態庫,所以此種方式編譯的程序,移到另一台機器上面也可以正常運行。
但是對於MD/MDd,連接的是動態庫,所以如果另一台機器上沒有MSVCRT.dll/MSVCRTD.dll時,就提示缺少動態庫這樣的錯誤。
曾經犯這樣的錯誤,以為以MT/MTd方式編譯,程序對所有的庫都是靜態鏈接的,其實錯了,它只能決定運行時庫是動態鏈接還是靜態鏈接,對用戶自己寫的庫或其他第三方庫,其連接方式取決於代碼(顯示連接動態庫Loadlibrary)或所提供的lib文件(為導入庫還是靜態庫),移動程序到別的機器上時,還是要帶上所需要的動態庫的。
來看一個例子,編譯一個靜態庫和一個動態庫,均實現兩個整數相加的功能:
// adds.h // add后面加個s代表靜態庫 #pragma once int add(int,int);
// adds.cpp // 靜態庫 #include "adds.h" int add(int a, int b) { return a+b; } 以上,運行時庫選擇MTd,編譯成靜態庫adds.lib
// addd.h // add后面加d代表動態庫 #pragma once #ifndef MYLIB_API #define MYLIB_API _declspec(dllexport) #endif MYLIB_API int add(int,int);
// addd.cpp // 動態庫 #include "addd.h" int add(int a, int b) { return a+b; }以上,運行時庫選擇MTd,編譯成動態庫addd.lib, addd.dll
// test.cpp // 測試程序 #include <iostream> // 測試靜態庫,此處為1,測試動態庫,此處為0 #define TEST_STATIC_LINK 1 #if TEST_STATIC_LINK #include <adds.h> #else #define MYLIB_API _declspec(dllimport) #include "addd.h" #endif using namespace std; int main() { cout << add(2,3) << endl; return 0; }測試程序以MTd編譯
1. 測試靜態庫,TEST_STATIC_LINK 定義為1,提供adds.lib,生成可執行文件,移動到另一台機器上可以運行,因為測試程序和adds.lib均靜態連接運行時庫
2. 測試動態庫,TEST_STATIC_LINK 定義為0,提供addd.lib,生成可執行文件,移動到另一台機器上可以運行,但需要addd.dll,因為addd庫靜態連接運行時庫,測試程序靜態連接運行時庫,動態連接addd庫
在上面的例子中add庫和測試程序均選擇MTd運行時庫,若不一致會導致一些編譯連接錯誤,讓新手不着頭腦。
比如adds選擇MDd,連接將會出現這樣的錯誤:
1>正在鏈接...
1>MSVCRTD.lib(ti_inst.obj) : error LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" (??0type_info@@AAE@ABV0@@Z) 已經在LIBCMTD.lib(typinfo.obj) 中定義
1>MSVCRTD.lib(ti_inst.obj) : error LNK2005: "private: class type_info & __thiscall type_info::operator=(class type_info const &)" (??4type_info@@AAEAAV0@ABV0@@Z) 已經在LIBCMTD.lib(typinfo.obj) 中定義
即一個程序中混合了不同的運行時庫(靜態庫和動態庫,調試庫和非調試庫),可能會產生沖突,所以一個程序中應該使用相同的運行時庫。