久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

AssertValid和Dump函數(shù)的應(yīng)用

 我的讀本 2010-09-21
CObject::AssertValid   成員函數(shù)提供對(duì)對(duì)象內(nèi)部狀態(tài)的運(yùn)行時(shí)檢查,。盡管從CObject派生類時(shí)不需要重寫 AssertValid,,但可以通過重寫使您的類更安全可靠,。AssertValid應(yīng)在對(duì)象的所有成員變量上執(zhí)行斷言,以驗(yàn)證它們包含有效值,。例如,,它應(yīng)檢查指針成員變量不為   NULL。 
  
  下面的示例顯示如何聲明   AssertValid   函數(shù): 
  class   CPerson   :   public   CObject 
  { 
  protected: 
        CString   m_strName; 
        float       m_salary; 
  public: 
  #ifdef   _DEBUG 
        virtual   void   AssertValid()   const;       //   Override 
  #endif 
        //   ... 
  }; 
  當(dāng)重寫   AssertValid   時(shí),,在執(zhí)行您自己的檢查之前請(qǐng)調(diào)用   AssertValid   的基類版本,。然后使用   ASSERT   宏檢查您的派生類特有的成員,,如下所示: 
  
  #ifdef   _DEBUG 
  void   CPerson::AssertValid()   const 
  { 
        //   call   inherited   AssertValid   first 
        CObject::AssertValid(); 
  
        //   check   CPerson   members... 
        ASSERT(   !m_strName.IsEmpty());   //   Must   have   a   name 
        ASSERT(   m_salary   >   0   );   //   Must   have   an   income 
  } 
  #endif 
  如果任何成員變量存儲(chǔ)對(duì)象,則可以使用   ASSERT_VALID   宏測(cè)試它們的內(nèi)部有效性(如果它們的類重寫了  AssertValid),。 
  
  例如,,考慮   CMyData   類,該類在其成員變量之一中存儲(chǔ)了一個(gè)   CObList,。CObList   變量   m_DataList   存儲(chǔ)了一個(gè)  CPerson   對(duì)象的集合,。CMyData   的簡(jiǎn)化聲明如下所示: 
  
  class   CMyData   :   public   CObject 
  { 
        //   Constructor   and   other   members   ... 
        protected: 
              CObList*   m_pDataList; 
        //   Other   declarations   ... 
        public: 
  #ifdef   _DEBUG 
              virtual   void   AssertValid(   )   const;   //   Override 
  #endif 
        //   Etc.   ... 
  }; 
  CMyData   中重寫的   AssertValid   如下所示: 
  
  #ifdef   _DEBUG 
  void   CMyData::AssertValid(   )   const 
  { 
        //   Call   inherited   AssertValid 
        CObject::AssertValid(   ); 
        //   Check   validity   of   CMyData   members 
        ASSERT_VALID(   m_pDataList   ); 
        //   ... 
  } 
  #endif 
  CMyData   使用   AssertValid   機(jī)制測(cè)試其數(shù)據(jù)成員中存儲(chǔ)的對(duì)象的有效性。CMyData   中重寫的   AssertValid   為它自己的   m_pDataList   成員變量調(diào)用   ASSERT_VALID   宏,。 
  
  因?yàn)?nbsp;  CObList   類也重寫   AssertValid,,所以有效性測(cè)試不在該級(jí)別停止。該重寫對(duì)列表的內(nèi)部狀態(tài)執(zhí)行附加有效性測(cè)試,。因此,,對(duì)   CMyData   對(duì)象的有效性測(cè)試將導(dǎo)致對(duì)存儲(chǔ)的   CObList   列表對(duì)象內(nèi)部狀態(tài)的附加有效性測(cè)試。 
  
  再多進(jìn)行一些操作,,還可以添加對(duì)存儲(chǔ)在列表中的   CPerson   對(duì)象的有效性測(cè)試,。可以從   CObList   派生   CPersonList   類,,并重寫   AssertValid,。在重寫中可調(diào)用   CObject::AssertValid,然后循環(huán)訪問列表,,在列表中存儲(chǔ)的每個(gè)   CPerson  對(duì)象上調(diào)用   AssertValid,。本主題開始所示的   CPerson   類已重寫了   AssertValid。 
  
  當(dāng)為調(diào)試生成時(shí),,這是一種功能極強(qiáng)的機(jī)制,。當(dāng)接著為發(fā)布生成時(shí),該機(jī)制自動(dòng)關(guān)閉,。 
  
  AssertValid   的限制 
  給定類的   AssertValid   函數(shù)的用戶應(yīng)注意該函數(shù)的限制,。觸發(fā)的斷言指示對(duì)象一定有誤,并且執(zhí)行將暫停,。但是,,缺少斷言只指示未找到任何問題,并不保證對(duì)象是好的,。 
 
Dump
當(dāng)從   CObject   派生類時(shí),,在使用   DumpAllObjectsSince   將對(duì)象轉(zhuǎn)儲(chǔ)到“輸出”窗口時(shí),可以重寫   Dump   成員函數(shù)以提供附加信息,。 
  
  Dump   函數(shù)將對(duì)象的成員變量的文本化表示形式寫入轉(zhuǎn)儲(chǔ)上下文   (CDumpContext),。轉(zhuǎn)儲(chǔ)上下文類似于   I/O   流。可以使用插入運(yùn)算符   (<<)   向   CDumpContext   發(fā)送數(shù)據(jù),。 
  
  重寫   Dump   函數(shù)時(shí),,應(yīng)先調(diào)用   Dump   的基類版本以轉(zhuǎn)儲(chǔ)基類對(duì)象的內(nèi)容。然后為派生類的每個(gè)成員變量輸出文本化說明和值,。 
  
  Dump   函數(shù)的聲明如下所示: 
  
  class   CPerson   :   public   CObject 
  { 
  public: 
  #ifdef   _DEBUG 
        virtual   void   Dump(   CDumpContext&   dc   )   const; 
  #endif 
  
        CString   m_firstName; 
        CString   m_lastName; 
        //   And   so   on... 
  }; 
  由于對(duì)象轉(zhuǎn)儲(chǔ)只在調(diào)試程序時(shí)有意義,,所以   Dump   函數(shù)的聲明用   #ifdef   _DEBUG   /   #endif   塊括起來。 
  
  在下面的示例中,,Dump   函數(shù)先為其基類調(diào)用   Dump   函數(shù),。然后,它將每個(gè)成員變量的簡(jiǎn)短說明與該成員的值一起寫入診斷流,。 
  
  #ifdef   _DEBUG 
  void   CPerson::Dump(   CDumpContext&   dc   )   const 
  { 
        //   Call   the   base   class   function   first. 
        CObject::Dump(   dc   ); 
  
        //   Now   do   the   stuff   for   our   specific   class. 
        dc   <<   "last   name:   "   <<   m_lastName   <<   "\n" 
              <<   "first   name:   "   <<   m_firstName   <<   "\n"; 
  } 
  #endif 
  必須提供   CDumpContext   參數(shù)以指定轉(zhuǎn)儲(chǔ)輸出的目的地。MFC   的“Debug”版本提供名為   afxDump   的預(yù)定義  CDumpContext   對(duì)象,,它將輸出發(fā)送到調(diào)試器,。 
  
  CPerson*   pMyPerson   =   new   CPerson; 
  //   Set   some   fields   of   the   CPerson   object. 
  //... 
  //   Now   dump   the   contents. 
  #ifdef   _DEBUG 
  pMyPerson->Dump(   afxDump   ); 
  #endif 
  在   MFC   程序中,可以使用   DumpAllObjectsSince   轉(zhuǎn)儲(chǔ)有關(guān)堆中尚未釋放的所有對(duì)象的說明,。DumpAllObjectsSince  轉(zhuǎn)儲(chǔ)自上個(gè)   CMemoryState::Checkpoint   以來分配的所有對(duì)象,。如果未發(fā)生   Checkpoint   調(diào)用,則  DumpAllObjectsSince   將轉(zhuǎn)儲(chǔ)當(dāng)前在內(nèi)存中的所有對(duì)象和非對(duì)象,。 
  
  注意       必須先啟用診斷跟蹤,,然后才能使用   MFC   對(duì)象轉(zhuǎn)儲(chǔ)。 
  注意       程序退出時(shí)   MFC   將自動(dòng)轉(zhuǎn)儲(chǔ)所有泄漏的對(duì)象,,因此不必創(chuàng)建代碼在該點(diǎn)轉(zhuǎn)儲(chǔ)對(duì)象,。 
  以下代碼通過比較兩個(gè)內(nèi)存狀態(tài)來測(cè)試內(nèi)存泄漏,并在檢測(cè)到泄漏時(shí)轉(zhuǎn)儲(chǔ)所有對(duì)象: 
  
  if(   diffMemState.Difference(   oldMemState,   newMemState   )   ) 
  { 
        TRACE(   "Memory   leaked!\n"   ); 
        diffMemState.DumpAllObjectsSince(); 
  } 
  轉(zhuǎn)儲(chǔ)的內(nèi)容如下所示: 
  
  Dumping   objects   -> 
  
  {5}   strcore.cpp(80)   :   non-object   block   at   $00A7521A,   9   bytes   long 
  {4}   strcore.cpp(80)   :   non-object   block   at   $00A751F8,   5   bytes   long 
  {3}   strcore.cpp(80)   :   non-object   block   at   $00A751D6,   6   bytes   long 
  {2}   a   CPerson   at   $51A4  
  Last   Name:   Smith 
  First   Name:   Alan 
  Phone   #:   581-0215  
  {1}   strcore.cpp(80)   :   non-object   block   at   $00A7516E,   25   bytes   long 
  大多數(shù)行開始處的大括號(hào)中的數(shù)字指定對(duì)象的分配順序,。最近分配的對(duì)象具有最高編號(hào),,并顯示在轉(zhuǎn)儲(chǔ)的頂部。 
 
靜態(tài)庫和動(dòng)態(tài)庫的區(qū)別:
首先糾正所謂“靜態(tài)連接就是把需要的庫函數(shù)放進(jìn)你的exe之中”的說法,。在真實(shí)世界中,,有三個(gè)概念:Use   static   libary, static   linked   DLL,dynamic linked   DLL. 多數(shù)人混淆了static libary和static linked DLL的概念,當(dāng)然他們有似是而非的“相似之處”,,比如都用到.lib,。  
使用靜態(tài)庫(Use   static   libary)是把.lib和其他.obj一起build在目標(biāo)文件中, 目標(biāo)文件可以是.exe,也可以是.dll或.oxc等,。
一般情況下,,可以根本就沒有“對(duì)應(yīng)的”.dll   文件,如C   Run   Time(CRT)庫,。一個(gè)例子就是,,寫一個(gè)main(){},build出來并不是只有幾個(gè)字節(jié),,當(dāng)然有人會(huì)說那還有exe文件頭呢,?是,,即使加上文件 頭的尺寸,build出的執(zhí)行文件仍然“莫名的大”,。實(shí)際上那多出來的部分就是CRT靜態(tài)庫,。姑且可以把靜態(tài)庫.lib理解成外部程序的obj文件比較合 理,它包含了函數(shù)的實(shí)現(xiàn),。           
下面再談static linked DLL和dynamic linked DLL又如何,?
靜態(tài)鏈接(static linked DLL)從操作上在VC的Project|Settings...|Link   (tab)|General   (category)|Object/library  modules   中設(shè)置和添加。比如要使用SDK中的PropertySheet()   API,   就要在這里添加   comctl32.lib,,然后再調(diào)用的源程序中#include   <prsht.h>,   使用的地方直接調(diào)用PropertySheet(),。當(dāng)程序.exe啟動(dòng)時(shí),系統(tǒng)會(huì)把對(duì)應(yīng)comctl32.dll加載進(jìn)來,。作為DLL的靜態(tài)引入庫 的.lib不包含函數(shù)的實(shí)現(xiàn),,只包含用于系統(tǒng)加載的信息,如對(duì)應(yīng)的DLL名稱,,函數(shù)歧視地只在對(duì)應(yīng)的DLL中的便宜等等,。相比動(dòng)態(tài)鏈接而言,靜態(tài)鏈接是很 簡(jiǎn)單的,。
動(dòng)態(tài)鏈接是使用LoadLibrary()/GetProcessAddress()和FreeLibrary().
  有人會(huì)想,,動(dòng)態(tài)鏈接這樣麻煩,為什么還要用呢,?這里有一個(gè)技術(shù)問題,,對(duì)這個(gè)問題的解決直接導(dǎo)致了動(dòng)態(tài)加載的需求。問題是有些DLL只在某個(gè)Windows 版本中存在,,或某個(gè)API只在某些Windows版本中被加入指定的DLL,。當(dāng)你使用靜態(tài)鏈接的.exe試圖在不支持的Windows版本上運(yùn)行時(shí),系統(tǒng) 會(huì)彈出系統(tǒng)對(duì)話框提示某某.dll無法加載或無法定位某某API的消息,,然后就中止.exe的運(yùn)行,。像這樣因?yàn)閭€(gè)別功能的實(shí)現(xiàn)依賴于某個(gè)DLL,當(dāng)這個(gè) DLL不可用時(shí)導(dǎo)致整個(gè).exe無法運(yùn)行是不明智的,。避免這樣的結(jié)局只有用動(dòng)態(tài)鏈接,。
 
#ifdef   _DEBUG                                                         //   判斷是否定義_DEBUG 
         #undef   THIS_FILE                                             //   取消THIS_FILE的定義 
         static   char   THIS_FILE[]=__FILE__;                          //   定義THIS_FILE指向文件名 
         #define  new    DEBUG_NEW                                      //   定義調(diào)試new宏,取代new關(guān)鍵字 
#endif                                                                  //   結(jié)束     
如果定義了_DEBUG,,表示在調(diào)試狀態(tài)下編譯,,因此相應(yīng)修改了兩個(gè)符號(hào)的定義
THIS_FILE是一個(gè)char數(shù)組全局變量,字符串值為當(dāng)前文件的全路徑,,這樣在Debug版本中當(dāng)程序出錯(cuò)時(shí)出錯(cuò)處理代碼可用這個(gè)變量告訴你是哪個(gè)文件中的代碼有問題,。
定義 _DEBUG后,由于定義了_DEBUG,編譯器確定這是一個(gè)調(diào)試,編譯#ifdef   _DEBUG和#endif之間的代碼,。#undef   表示清除當(dāng)前定義的宏,,使得THIS_FILE無定義。__FILE__   是編譯器能識(shí)別的事先定義的ANSI   C   的6個(gè)宏之一,。#define   new  DEBUG_NEW 
DEBUG_NEW定位內(nèi)存泄露并且跟蹤文件名.

在用vc時(shí),,利用AppWizard會(huì)產(chǎn)生如下代碼:
#ifdef _DEBUG
          #define new DEBUG_NEW
          #undef THIS_FILE
          static char THIS_FILE[] = __FILE__;
#endif
對(duì)于
#define new DEBUG_NEW
首先看msdn的解釋:
Assists in finding memory leaks. You can use DEBUG_NEW everywhere in your program that you would ordinarily use the new operator to allocate heap storage.
In debug mode (when the _DEBUG symbol is defined), DEBUG_NEW keeps track of the filename and line number for each object that it allocates. Then, when you use the CMemoryState::DumpAllObjectsSince member function, each object allocated with DEBUG_NEW is shown with the filename and line number where it was allocated.
To use DEBUG_NEW, insert the following directive into your source files:
#define new DEBUG_NEW
Once you insert this directive, the preprocessor will insert DEBUG_NEW wherever you use new, and MFC does the rest. When you compile a release version of your program, DEBUG_NEW resolves to a simple new operation, and the filename and line number information is not generated.

再查看定義:
#ifdef _DEBUG
          void* AFX_CDECL operator new(size_t nSize, LPCSTR lpszFileName, int nLine);
          #define DEBUG_NEW new(THIS_FILE, __LINE__)
#else
          #define DEBUG_NEW new
#endif
這樣就很清楚了,當(dāng)在debug模式下時(shí),,我們分配內(nèi)存時(shí)的new被替換成DEBUG_NEW,,而這個(gè)DEBUG_NEW不僅要傳入內(nèi)存塊的大小,還要傳入源文件名和行號(hào),,這就有個(gè)好處,,即當(dāng)發(fā)生內(nèi)存泄漏時(shí),我們可以在調(diào)試模式下定位到該問題代碼處,。若刪掉該句,,就不能進(jìn)行定位了。而在release版本下的new就是簡(jiǎn)單的new,,并不會(huì)傳入文件名和行號(hào)。
因此,,我們?cè)陂_發(fā)代碼階段,,保留上述代碼是值得的。

本文來自CSDN博客,,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/jiaoshuchun/archive/2010/01/13/5186743.aspx

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多