zoukankan      html  css  js  c++  java
  • AssertValid函数学习

    转自http://tsitao.blog.163.com/blog/static/29795822006914105840496/

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

    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
    大多数行開始处的大括号里的数字指定对象的分配顺序。近期分配的对象具有最高编号,并显示在转储的顶部。

    AssertValid函数是用来推断表达式的合法性或正确性,假设不对或不合法则终止程序并返回对应的提示信息
    如AssertValid(t==0);//用来推断t是否等于0,假设t!=0则终止程序
    Dump函数一般用来显示debug信息的,其函数中的内容一般在debug时,在debug窗体中才干看到。
  • 相关阅读:
    KindEditor限制输入字数
    datepicker日历控件使用
    复合注解的解析
    jdk包结构及用途分析
    深入理解BIO、NIO、AIO
    MiniCat:手写Http服务器
    基于TCP协议的Socket编程
    手写一个最迷你的Web服务器
    手写一个Web服务器,极简版Tomcat
    java网络编程socket的使用
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4201208.html
Copyright © 2011-2022 走看看