MFC中進階調試技術

來源:互聯網
上載者:User

 MFC中進階調試技術

1. TRACE宏的利用

    TRACE宏有點像我們以前在C語言中用的printf函數,使程式在運行過程中輸出一些調試資訊,使我們能瞭解程式的一些狀態。但有一點不同的是,TRACE宏只有在調試狀態下才有輸出,而以前用的Printh函數在任何情況下都有輸出。同printf函數一樣,TRACE宏可以接受多個參數,如:

    int x = 1;

    int y = 16;

    float z = 32.0;

    TRACE( "This is a TRACE statement/n" );

    TRACE( "The value of x is %d/n", x );

    TRACE( "x = %d and y = %d/n", x, y );

    TRACE( "x = %d and y = %d and z = %f ", x, y, z );

    要注意的是TRACE宏只對Debug版本的工程產生作用,在Release版本的工程中,TRACE宏將被忽略。

2. ASSERT宏的利用

      在開發過程中我們可以假設只要程式運行正確,某一條件肯定成立。若不成立,那麼我們可以斷言程式肯定出錯。在這種情況下我們可要利用ASSERT來設定斷言。ASSERT宏的參數是一個邏輯運算式,在程式運行過程中,若該邏輯運算式為真,則不會發生任何動作;若此運算式為假,則系統彈出一個對話方塊警告你,並停止程式的執行。同時要求你作出選擇:取消、忽略和重試。若你選擇取消,則系統將停止程式的運行;若你選擇忽略,則系統將忽略該錯誤,並繼續執行程式;若你選擇重試,則系統將重新計算該運算式,並啟用調試器。同TRACE宏一樣,ASSERT宏只對Debug版本的工程產生作用,在Release版本的工程中,TRACE宏將被忽略。

     下面的樣本顯示如何使用ASSERT檢查函數的傳回值:

      int x = SomeFunc(y);

      ASSERT( x >=  0);   // 如果x為負,則宣告失敗。

     可將斷言用於:

     (1)可以使用Assert 陳述式捕捉邏輯錯誤。可以在程式邏輯必須為真的條件上設定斷言。除非發生邏輯錯誤,否則斷言對程式無任何影響。

      (2)可以使用Assert 陳述式檢查操作的結果。斷言對於快速直觀地檢查不明顯的操作結果最有價值。

      (3)可以使用斷言在代碼中已處理了錯誤的點處測試錯誤類型。

3. ASSERT_VALID宏的使用

   ASSERT_VALID宏用來在程式運行時檢查一個對象的內部合法性。比如說,現在有一個學生對象,我們知道每一個學生的年齡一個大於零,若年齡小於零,則該學生對象肯定有問題。事實上,ASSERT_VALID宏就是轉化為對象的成員函數AssertValid的調用,只是這中方法更安全。它的參數是一個對象指標,通過這個指標來調用它的AssertValid成員函數。

   與此相配套,每當建立從CObject類繼承而來的一個新類時,可以重載該成員函數,以執行特定的合法性檢查。下面的樣本顯示如何聲明AssertValid函數:

sclass CPerson : public CObject

{

protedted:

         CString m_strName;

         float m_salary;

public:

       #ifdef _DEBUG

           virtual void AssertValid( ) const;   // Override

      #endif

      // .....

};

      當重寫AssertValid時,在執行程式的檢查之前請調用AssertValid的基類模板。然後使用ASSERT宏來檢查衍生類別特有的成員,如下所示:

#ifdef _DEBUG

void CPerson::AssertValid( ) const

{

     // call inherited AssertValid first

     CObject::AssertValid( );

    // check CPerson menbers...

    ASSERT( !m_strName.IsEmpty( ) );    // Must have a name

    ASSERT( m_salary > 0 );                  // Must have an income

}

#endif

4. 記憶體漏洞的檢查

    在C++和C語言中指標問題也就是記憶體申請與釋放是一個令人頭疼的事情,假如申請了記憶體,但沒有釋放,並且程式需要長時間的運行,那麼,系統資源將逐漸減少。當系統的資源全部用完時,系統將崩潰。所以在開發過程中一定要保證資源的完全釋放。

    檢查記憶體漏洞的方法如下:

    假如要檢查某一程式段是否有記憶體漏洞,只需在這一程式段的開始要求系統做一次記憶體使用量情況的映射,記錄下程式開始時的記憶體使用量情況,然後在程式段的末尾再使系統做一次記憶體映射。比較兩次映射,以檢查是否有未釋放的記憶體,加入有未釋放的記憶體,根據這一塊中有關分配情況的資訊來告訴使用者在那裡申請的記憶體未釋放。

    具體的講,檢查記憶體漏洞需要一下幾步:

    (1)在所檢測的程式段開始處建立一個CmemoryState對象,調用其成員函數Checkpoint,以取得當前記憶體使用量情況的映射;

    (2)在所檢測的程式段的末尾處再建立一個CmemoryState對象,調用其成員函數Checkpoint,以取得當前記憶體使用量情況的映射;

    (3)再建立第3個CmemoryState對象,調用其成員函數Difference,把第一個CmemoryState對象和第二個CmemoryState對象作為其參數,如果兩次記憶體映射不相同,則該函數返回非零,說明此程式段中有記憶體漏洞。

      下面來看一個例子:

       #ifdef _DEBUG

       CMemoryState oldMemState, newMemState,  diffMemState;

       oldMemState.Checkpoint();

       #endif

       CString s = "This is a frame variable";

       // the next object is a heap object

       CPerson* p = new CPerson("Smith", "Alan", "581_0215");

      #ifdef _DEBUG

      newMemState.Checkpoint();

      if ( diffMemState.Difference(oldMemState, newMemState ) )

      {

           TRACE("Memory Leaked!/n");

      }

    在此例中,首先定義了3個CMemoryState對象。然後在需要檢測記憶體漏洞的代碼前後分別調用CMemoryState對象成員函數Checkpoint,再後調用第3個CMemoryState對象的成員函數Difference來判斷是否有記憶體漏洞,如果有,則使用TRACE宏列印提示訊息。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.