1. assert 函式
一般在做 trace 時,似乎比較少人用到 assert,assert 裡面放的判斷是,如果「不成立的話」,程式便不會繼續執行下去。以下述程式碼而言
#include <stdio.h> #include <assert.h> int main() { int a=10, b=0; assert(!(b==0)); printf("%d\n", a/b); return 0; }
執行時將出現以下視窗
console 那裡結果如下
Assertion failed: !(b==0), file d:\vctest\main.c, line 6
但這種方式,是不論為 release mode 或 debug mode,都會顯示此訊息。
一些書之 tips 裡,會提到,在做 release 時,將相關 debug 函式全都拿掉會是較好的做法。
意思是,當程式 release 給 client 時,所有 assert 都拿掉會較佳。
如此一來,debug 完,到時又把 assert 全拿掉又顯得費時,於是用一些條件式鍽譯技巧,
進行轉換。
2. 自定義 __degug.c , __debug.h
再加入
/* filename : __debug.h */ #ifndef __DEBUG_H__ #define __DEBUG_H__ #ifdef _DEBUG void _trace(char *fmt, ...); #define ASSERT(x) {if(!(x)) _asm{int 0x03}} #define VERIFY(x) {if(!(x)) _asm{int 0x03}} #else #define ASSERT(x) #define VERIFY(x) x #endif #ifdef _DEBUG #define TRACE _trace #else inline void _trace(LPCTSTR fmt, ...) { } #define TRACE 1 ? (void)0 : _trace #endif #endif // __DEBUG_H__
/* filename : __debug.c */ #ifdef _DEBUG #include <stdio.h> #include <stdarg.h> #include <windows.h> void _trace(char *fmt, ...) { char out[1024]; va_list body; va_start(body, fmt); vsprintf(out, fmt, body); va_end(body); OutputDebugString(out); } #endif
直接拿一個測試程式碼出來
#include <stdio.h> #include "__debug.h" int main() { int a=10, b=0; ASSERT(!(b==0)); printf("%d\n", a/b); return 0; }
執行結果與上述相仿
但這支測試程式碼之 ASSERT ,只在「偵錯」時有作用,在發佈出去「執行」時將不具作用。
3. TRACE
上述 __debug.h 裡面還提到了 TRACE,一般新手在做 trace 時,
會以 printf 方式輸出到 console 視窗上面去,
這裡的 TRACE 則是直接將結果輸出到 IDE 裡的「輸出」視窗裡面去。
#include <stdio.h> #include "__debug.h" int main() { int x=0, sum=0; for(x=0; x<=10; ++x) { sum+=x; TRACE("x=%d, sum=%d\n", x, sum); } return 0; }
輸出結果在 console 視窗看不到,只會在 IDE 裡之「輸出視窗」看到結果
文章標籤
全站熱搜

用函數實作 trace 有一些小小的缺點。其中之一是必須依賴 inline 機制才有辦法在 release build 徹底消除不必要的呼叫,這點對現代的編譯器都不是問題。另一個問題是參數裡面的運算式有可能會被執行。 比較保險的作法應該是使用巨集配合 __VA_ARGS__ 實作,只是太舊的編譯器可能會無法支援。 在 C++ 底下可以玩的把戲就很多了,我在這裡有提到一些後端輸出的程式庫 http://novus.pixnet.net/blog/post/27548040 改天我也來寫一篇介紹一下 debug 前端的介面好了
感謝您的補充與提醒,我比較納悶的是,「參數裡面的運算式有可能會被執行」,這問題我想半天想不透為何可能會被執行。__VA_ARGS__ 這方式之前沒想過,有空會研究一下怎包出來做應用。連上了您的網站,有機會我也去借本 Applied C++: Practical Techniques for Building Better Software 出來看看好了。 最後謝謝您的回覆,讓我知道了許多我不知道的缺點、技巧,再次感謝! *^_^*
trace 的部份我沒仔細看成是碼,應該是我說錯了 關於實作上的一些考量可以參考 http://www.jeffhung.net/blog/articles/jeffhung/1013/ (我在最下面的 comment 就是你在這裡的作法,但我po出才發現犯了一個小小的錯誤,哈) 其實我並不特別推薦Applied C++: Practical Techniques for Building Better Software 當中的方案,我比較推薦你去讀 google log 的原始碼,他可以作到非常細微的控制,像是讓某些模組在 release build仍然會輸出除錯資訊,另一些模組則完全關閉除錯。他還提供了獨立於 NDEBUG 的除錯層級,像是關閉所有 level 4 以下的除錯資訊,但以上的資訊仍然照常輸出。
謝謝補充。感到很可惜回覆沒辦法按「讚」,這些回覆提到的東西對我幫助很大,再次感謝。
第一部分 「但這種方式,是不論為 release mode 或 debug mode,都會顯示此訊息。」 可以 #define NDEBUG 就可以當release version了 @@ http://www.cplusplus.com/reference/cassert/assert/
疑!之前沒注意到這點說明,謝謝提供。