VC的调试中,AssertValid和Dump函数的应用(转)

VC的调试中,AssertValid和Dump函数的应用(转)

概括的讲,AssertValid函数是用来判断表达式的合法性或正确性,如果不正确或不合法则终止程序并返回相应的提示信息  
  如AssertValid(t==0);//用来判断t是否等于0,如果t!=0则终止程序  
  Dump函数一般用来显示debug信息的,其函数中的内容一般在debug时,在debug窗口中才能看到。  
 
CObject::AssertValid   成员函数提供对对象内部状态的运行时检查。尽管从   CObject   派生类时不需要重写   AssertValid,但可以通过重写使您的类更安全可靠。AssertValid   应在对象的所有成员变量上执行断言,以验证它们包含有效值。例如,它应检查指针成员变量不为   NULL。  
   
  下面的示例显示如何声明   AssertValid   函数:  
  class   CPerson   :   public   CObject  
  {  
  protected:  
        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   members...  
        ASSERT(   !m_strName.IsEmpty());   //   Must   have   a   name  
        ASSERT(   m_salary   >   0   );   //   Must   have   an   income  
  }  
  #endif  
  如果任何成员变量存储对象,则可以使用   ASSERT_VALID   宏测试它们的内部有效性(如果它们的类重写了   AssertValid)。  
   
  例如,考虑   CMyData   类,该类在其成员变量之一中存储了一个   CObList。CObList   变量   m_DataList   存储了一个   CPerson   对象的集合。CMyData   的简化声明如下所示:  
   
  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   机制测试其数据成员中存储的对象的有效性。CMyData   中重写的   AssertValid   为它自己的   m_pDataList   成员变量调用   ASSERT_VALID   宏。  
   
  因为   CObList   类也重写   AssertValid,所以有效性测试不在该级别停止。该重写对列表的内部状态执行附加有效性测试。因此,对   CMyData   对象的有效性测试将导致对存储的   CObList   列表对象内部状态的附加有效性测试。  
   
  再多进行一些操作,还可以添加对存储在列表中的   CPerson   对象的有效性测试。可以从   CObList   派生   CPersonList   类,并重写   AssertValid。在重写中可调用   CObject::AssertValid,然后循环访问列表,在列表中存储的每个   CPerson   对象上调用   AssertValid。本主题开始所示的   CPerson   类已重写了   AssertValid。  
   
  当为调试生成时,这是一种功能极强的机制。当接着为发布生成时,该机制自动关闭。  
   
  AssertValid   的限制  
  给定类的   AssertValid   函数的用户应注意该函数的限制。触发的断言指示对象一定有误,并且执行将暂停。但是,缺少断言只指示未找到任何问题,并不保证对象是好的。  
/
当从   CObject   派生类时,在使用   DumpAllObjectsSince   将对象转储到“输出”窗口时,可以重写   Dump   成员函数以提供附加信息。  
   
  Dump   函数将对象的成员变量的文本化表示形式写入转储上下文   (CDumpContext)。转储上下文类似于   I/O   流。可以使用插入运算符   (<<)   向   CDumpContext   发送数据。  
   
  重写   Dump   函数时,应先调用   Dump   的基类版本以转储基类对象的内容。然后为派生类的每个成员变量输出文本化说明和值。  
   
  Dump   函数的声明如下所示:  
   
  class   CPerson   :   public   CObject  
  {  
  public:  
  #ifdef   _DEBUG  
        virtual   void   Dump(   CDumpContext&   dc   )   const;  
  #endif  
   
        CString   m_firstName;  
        CString   m_lastName;  
        //   And   so   on...  
  };  
  由于对象转储只在调试程序时有意义,所以   Dump   函数的声明用   #ifdef   _DEBUG   /   #endif   块括起来。  
   
  在下面的示例中,Dump   函数先为其基类调用   Dump   函数。然后,它将每个成员变量的简短说明与该成员的值一起写入诊断流。  
   
  #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   参数以指定转储输出的目的地。MFC   的“Debug”版本提供名为   afxDump   的预定义   CDumpContext   对象,它将输出发送到调试器。  
   
  CPerson*   pMyPerson   =   new   CPerson;  
  //   Set   some   fields   of   the   CPerson   object.  
  //...  
  //   Now   dump   the   contents.  
  #ifdef   _DEBUG  
  pMyPerson->Dump(   afxDump   );  
  #endif  
  在   MFC   程序中,可以使用   DumpAllObjectsSince   转储有关堆中尚未释放的所有对象的说明。DumpAllObjectsSince   转储自上个   CMemoryState::Checkpoint   以来分配的所有对象。如果未发生   Checkpoint   调用,则   DumpAllObjectsSince   将转储当前在内存中的所有对象和非对象。  
   
  注意       必须先启用诊断跟踪,然后才能使用   MFC   对象转储。  
  注意       程序退出时   MFC   将自动转储所有泄漏的对象,因此不必创建代码在该点转储对象。  
  以下代码通过比较两个内存状态来测试内存泄漏,并在检测到泄漏时转储所有对象:  
   
  if(   diffMemState.Difference(   oldMemState,   newMemState   )   )  
  {  
        TRACE(   "Memory   leaked!/n"   );  
        diffMemState.DumpAllObjectsSince();  
  }  
  转储的内容如下所示:  
   
  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  
  大多数行开始处的大括号中的数字指定对象的分配顺序。最近分配的对象具有最高编号,并显示在转储的顶部。  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值