防禦性編程是提高軟體品質技術的有益輔助手段,它的主要思想是:子程式應該不因傳入錯誤資料而被破壞,哪怕是由其他子程式產生的錯誤資料。防禦性編程關鍵在於嚴格的輸入檢查、預期的錯誤處理方法。下面介紹使用斷言來進行防禦性編程。
斷言通常是一個常式(routine)或一個宏(macros),斷言通常包含有兩個參數:布林運算式和訊息。布林運算式的反面是一個錯誤,C標準庫提供了一個assert宏,它只帶有一個參數,如:
assert(1==0);
//注意布林運算式不用加引號
使用assert宏,需要包含標頭檔cassert或assert.h,執行上述語句的結果是程式結束運行,並彈出對話方塊顯示出錯資訊。
我們可以自訂assert宏,有兩個目的:
1)新增參數。例如新增一個訊息參數,使assert宏輸出更為豐富的資訊;
2)改變assert的行為內容。C標準庫中的assert宏將中斷程式,可以讓程式繼續運行而不中斷或者進入調試狀態等,另外還可以控制訊息輸出的目標,即控制訊息是輸出到控制台還是文字檔,甚至是通過網路發出。
下面是一個C++實現的自訂斷言:
#ifdef _DEBUG
#define Assert(exp, message)
/
{
/
if(!(exp))
/
{ /
std::cout<<"Assertion failed: "<<#exp<<"/n"
/
<<"Message: "<<message<<"/n"
/
<<"line: "<<__LINE__<<"/n"
/
<<"file: "<<__FILE__<<"/n";
/
exit(EXIT_FAILURE); /
} /
}
#else
#define Assert(exp, message)
#endif
使用斷言應注意的問題:
1)對非預期錯誤使用斷言。非預期錯誤包括null 指標、輸入或輸出的參數值不在預期範圍內、數組的越界等;
2)不要把需要執行的代碼放入斷言中。斷言用於軟體的開發和維護,通常不在發行版本中包含斷言。把需要啟動並執行代碼放入斷言中,在發行版本中這些代碼通常不會被執行;
3)對來源於內部系統的可靠資料使用斷言,而不要對外部不可靠資料使用斷言,對於外部不可靠資料應該使用錯誤處理代碼。