使用模擬器開Xamarin專案時,一直無法順利開啟,後來才發現應該是要選擇Debug mode而非release mode,但是到底這兩者有何差異呢?
上網查了查,發現
Debug版:包含Microsoft格式的除錯資訊,沒有進行最佳化,檔案體積較大
Release版:不包含除錯資訊,有針對執行速度最佳化,檔案體積較小
看起來這兩者好像沒有太大的差異,但為什麼會發生,debug能跑,但release會出錯的事情呢?
事實上Debug 和 Release 並沒有本質的界限,他們只是一組編譯選項的集合,編譯器只是按照預定的選項行動。
出錯的原因很多,有興趣可以看參考資料與下列網路搜尋到的資訊。基本上我會理解如果開發程式,一般還是選擇debug mode,如果要佈板,發佈出去考慮到效能OOXX了話,我會使用release mode。
Debug各參數的定義:
Release各參數的定義:
- Runtime Library差異(MDd和MD)
Runtime Library 包含了除錯用的訊息,並採用了一些保護機制以幫助發現錯誤,所以性能上較不如Release的版本。編譯器提供的 Runtime Library通常很穩定不會造成 Release 版本錯誤;倒是由於 Debug 的 Runtime Library 加強了對錯誤的檢測,如Heap的記憶體分配,有時會出現Debug 有錯但 Release 正常的現象。這裡要注意的是,如果 Debug 有錯,即使 Release 正常,程式保證是有 Bug 的,只不過可能是 Release 版的某次執行沒有表現出來而已。
- 最佳化的影響(O1和O2)
在函式的呼叫過程中,所有呼叫的訊息(回傳位址、參數)以及自動變數都是放在堆疊中的。如果函式的宣告跟實作不同(參數、回傳值、呼叫方式),就會產生錯誤,但 Debug 方式下,堆疊的存取透過 EBP 暫存器儲存的位址來實現,如果沒有發生陣列越界之類的錯誤(或是越界「不多」),函式通常能正常執行;Release 方式下,最佳化會省略 EBP 堆疊基本位址的指標,這樣通過一個全域指標存取堆疊,可能就會造成回傳位址錯誤導致整個程式崩潰。
當您建置專案進行偵錯時,您是使用偵錯記憶體配置器 (Debug Memory Allocator)。這表示所有的記憶體配置周圍都放置了保護位元組。這些保護位元組會偵測記憶體覆寫。由於Release的組建與Debug版的堆積配置不同,在Debug中的記憶體覆寫可能不會造成任何問題,但在Release的組建中卻可能產生災難性的影響。
- 變數的初始化(GZ的選項)
Deug通常會將記憶體和變數做初始化,包括用 0xCC 初始化所有自動變數,0xCD(Cleared Data)初始化Heap中分配的記憶體(即動態分配的記憶體,例如 new ),0xDD ( Dead Data ) 填充已被釋放的Heap記憶體(例如delete),0xFD(deFencde Data)初始化受保護的記憶體(debug 版在動態分配記憶體的前後加入保護記憶體以防止越界存取).
Release 版中未初始化的變量是隨機的(沒有初始化),這有可能使指針指向一個有效地址而掩蓋了非法訪問.
- DEBUG 與 NDEBUG
當定義了 _DEBUG 時,ASSERT() 函式會被編譯,而 NDEBUG 時不被編譯。此外,TRACE() 巨集的編譯也受 _DEBUG 控制有些人會自行定義#ifdef _DEBUG 之類的條件編譯,必須注意。
Reference:
http://johnniebooks.blogspot.com/2009/05/debug-release.html