• 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窗体中才干看到。
  • 相关阅读:
    飞入飞出效果
    【JSOI 2008】星球大战 Starwar
    POJ 1094 Sorting It All Out
    POJ 2728 Desert King
    【ZJOI 2008】树的统计 Count
    【SCOI 2009】生日快乐
    POJ 3580 SuperMemo
    POJ 1639 Picnic Planning
    POJ 2976 Dropping Tests
    SPOJ QTREE
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4068902.html
Copyright © 2020-2023  润新知