第六篇:使用前處理器幫助除錯

穆晨發表於2017-01-26

前言

       你是否遇到過以下情況?

       情況一:為了除錯方便,程式碼中夾雜各種cout語句。當除錯好了,把這些語句刪了,執行“正式版”後,又發現新問題,只得把這些cout語句一個個新增回去再進行除錯。如此不斷迴圈。

       情況二:希望在程式碼中獲取到原始檔的檔名,當前程式碼行號,編譯時間等資訊。

       情況三:糾結於是否實現某些概率極低(幾乎不存在)的錯誤檢測

       如果有,那麼這篇隨筆適合你,或者說,前處理器帶來的除錯技術適合你。

技巧一:設定除錯區程式碼開關

       請看下面的原始碼:

 1 #include <iostream>
 2  
 3 using namespace std;
 4  
 5 int main()
 6 {
 7     /*
 8     * 原始碼區一
 9     */
10 
11     #ifdef DEBUG1
12     cout << "DEBUG1" << endl;
13     #endif
14  
15     /*
16      * 原始碼區二
17     */
18 
19     #ifdef DEBUG2
20     cout << "DEBUG2" << endl;
21     #endif
22 
23     /*
24      * 原始碼區三
25     */
26 
27     return 0;
28  }

       兩段包含cout語句的程式碼段都是除錯語句,而兩個巨集DEBUG1和DEBUG2就是所謂的開關。現在假設我想執行上面的那段除錯程式碼,則可以輸入以下指令開啟DEBUG1開關並完成編譯(這條命令等效於在原始檔開頭加上#define DEBUG1再編譯):

1 g++ -DDEBUG1 1.cpp -o run

       執行結果如下:

  

  結果顯示DEBUG1開關對應的除錯語句得到執行。可以用同樣的方法操縱開關DEBUG2及其對應除錯程式碼。明白了吧,你可以通過開啟開關自由地選擇需要編譯並執行的除錯區程式碼

技巧二:使用預定義巨集獲取相關資訊

       前處理器提供了一些預定義的巨集可獲取編譯,檔案的相關資訊,參見下面程式碼:

 1 #include <iostream>
 2 
 3 using namespace std; 
 4 
 5 int main()
 6 {
 7     cout << "檔名: " << __FILE__ << endl;
 8     cout << "當前行號: " << __LINE__ << endl;
 9     cout << "編譯日期: " << __DATE__ << endl;
10     cout << "編譯時間: " << __TIME__ << endl;
11 
12     return 0;
13 }

       執行結果:

       

技巧三:使用assert斷言巨集確保某個條件不發生

  基本格式為 assert(表示式)。當表示式為真,語句不做任何事情,否則語句輸出錯誤並終止程式執行,請看下面程式碼:

 1 #include <iostream>
 2 #include <cassert>    // 要使用assert斷言巨集必須包含這個標頭檔案
 3  
 4 using namespace std;
 5  
 6 int main()
 7 {
 8     int t=0;
 9     cin >> t;
10 
11     assert (t !=0);
12     cout << "t: " << t << endl;
13  
14     return 0;
15 }

       assert在這裡的作用是確保t不等於0。如果t=0,程式會彈出錯誤並停止執行。編譯程式碼並執行,

       當輸入為0時執行結果:

       

       當輸入其他數字時執行結果:

       

       最後要強調的是,assert只是除錯工具,它絕對不能代替邏輯檢查參與到異常處理中

相關文章