一、Debug和Realease區別產生的原因
Debug 通常稱為調試版本,它包含調試信息,並且不作任何優化,便於程序員調試程序。Release 稱為發布版本,它往往是進行了各種優化,使得程序在代碼大小和運行速度上都是最優的,以便用戶很好地使用。
Debug 和 Release 的真正區別,在於一組編譯選項。
Debug 版本
參數 含義
/MDd /MLd 或 /MTd 使用 Debug runtime library(調試版本的運行時刻函數庫)
/Od 關閉優化開關
/D "_DEBUG" 相當於 #define _DEBUG,打開編譯調試代碼開關(主要針對assert函數)
/ZI
創建 Edit and continue(編輯繼續)數據庫,這樣在調試過程中如果修改了源代碼不需重新編譯
GZ 可以幫助捕獲內存錯誤
Release 版本
參數 含義
/MD /ML 或 /MT 使用發布版本的運行時刻函數庫
/O1 或 /O2 優化開關,使程序最小或最快
/D "NDEBUG" 關閉條件編譯調試代碼開關(即不編譯assert函數)
/GF 合並重復的字符串,並將字符串常量放到只讀內存,防止被修改
Debug 和 Release 並沒有本質的界限,他們只是一組編譯選項的集合,編譯器只是按照預定的選項行動。
相關經驗: 轉自http://dev.csdn.net/article/17/17068.shtm
二、Debug和Realease區別的表現
I. 內存分配問題
- 變量未初始化。下面的程序在debug中運行的很好。
thing * search(thing * something)
BOOL found;
for(int i = 0; i < whatever.GetSize(); i++)
{
if(whatever[i]->field == something->field)
{ /* found it /
found = TRUE;
break;
} / found it */
}
if(found)
return whatever[i];
else
return NULL;
而在release中卻不行,因為debug中會自動給變量初始化found=FALSE,而在release版中則不會。所以盡可能的給變量、類或結構初始化。
- 數據溢出的問題
如:char buffer[10];
int counter;
lstrcpy(buffer, "abcdefghik");
在debug版中buffer的NULL覆蓋了counter的高位,但是除非counter>16M,什么問題也沒有。但是在release版 中,counter可能被放在寄存器中,這樣NULL就覆蓋了buffer下面的空間,可能就是函數的返回地址,這將導致ACCESS ERROR。
- DEBUG版和RELEASE版的內存分配方式是不同的 。如果你在DEBUG版中申請 ele 為 6*sizeof(DWORD)=24bytes,實際上分配給你的是32bytes(debug版以32bytes為單位分配), 而在release版,分配給你的就是24bytes(release版以8bytes為單 位),所以在debug版中如果你寫ele[6],可能不會有 什么問題,而在release版中,就有ACCESS VIOLATE。
相關經驗,轉自http://www.cnblogs.com/JemBai/archive/2009/01/13/1374805.html
三、靜態庫和動態庫的區別
靜態連接庫就是把(lib)文件中用到的函數代碼直接鏈接進目標程序,程序運行的時候不再需要其它的庫文件;動態鏈接就是把調用的函數所在文件模塊(DLL)和調用函數在文件中的位置等信息鏈接進目標程序,程序運行的時候再從DLL中尋找相應函數代碼,因此需要相應DLL文件的支持。
靜態編譯只需要所需的頭文件和對應的lib庫文件。
動態編譯則需要所需的頭文件、對應的lib庫文件以及對應的dll庫文件。
事實上,靜態編譯用到的庫文件和動態編譯用到的庫文件有本質區別:前者靜態庫是一個或者多個obj文件的打包,所以有人干脆把從obj文件生成lib的過程稱為Archive,即合並到一起。比如你鏈接一個靜態庫,如果其中有錯,它會准確的找到是哪個obj有錯,即靜態lib只是殼子。而后者為動態連接庫(DLL)的導入庫,它告訴鏈接器調用的函數在哪個DLL中,函數執行代碼在DLL中的什么位置,這也就是為什么需要附加依賴項 .LIB文件,它起到橋梁的作用。
四、VS中/MT、/MD、/MTd、/MDd的區別
1.Overview
目前,在VS中提供的運行時庫分為靜態鏈接庫和動態鏈接庫兩類,而每一類運行時庫又可再分為 debug 版和 release 版,因此VS共提供了 4 個運行時庫。如下表:
C 運行時庫 庫文件
MultiThread(static link) MT libcmt.lib
Debug multiThread(static link) MTd libcmtd.lib
MultiThread(dynamic link) MD msvert.lib
Debug multiThread(dynamic link) MDd msvertd.lib
2.各運行時庫的區別
a.靜態鏈接的多線程庫
靜態鏈接的多線程庫的目標代碼也最終被編譯在應用程序的二進制文件中,但是它可以在多線程程序中使用。通過 /MT 編譯選項可以設置 Visual C++ 使用靜態鏈接的單線程庫。
b.動態鏈接的運行時庫
動態鏈接的運行時庫將所有的 C 庫函數保存在一個單獨的動態鏈接庫 MSVCRTxx.DLL 中, MSVCRTxx.DLL 處理了多線程問題。使用 /MD 編譯選項可以設置 Visual C++ 使用動態鏈接的運行時庫。
/MDd 或 /MTd 選項使用 Debug runtime library( 調試版本的運行時刻函數庫 ) ,與 /MD 或 /MT 分別對應。 Debug 版本的 Runtime Library 包含了調試信息,並采用了一些保護機制以幫助發現錯誤,加強了對錯誤的檢測,因此在運行性能方面比不上 Release 版本。
3.運行時庫的選擇
根據最近的項目經驗,如果項目中包含了其它編譯好的lib靜態庫文件,就使用/MT。
總之要保持一致性。否則可能會出現鏈接錯誤:LINK2005或LINK2038等等。