AssertValid函数学习 .「建议收藏」

AssertValid函数学习 .「建议收藏」转自http://tsitao.blog.163.com/blog/static/29795822006914105840496/ VC的调试中,AssertValid和Dump函数的应用CObject::AssertValid成员函数提供对对象内部状态的运行时检查。尽管从CObject派生类时不需要重写AssertValid,但可以通过重写使您的类更安全可靠。Asse

大家好,又见面了,我是你们的朋友全栈君。

转自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窗口中才能看到。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/159058.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Python基础知识归纳「建议收藏」

    Python基础知识归纳「建议收藏」Python基础教程Python基础教程Python简介Python环境搭建Python中文编码Python基础语法Python变量类型Python运算符Python条件语句Python循环语句PythonWhile循环语句Pythonfor循环语句Python循环嵌套Pythonbreak语句Python…

    2022年10月16日
    0
  • VBScript教程之一(Hello VBScriopt)「建议收藏」

    VBScript教程之一(Hello VBScriopt)「建议收藏」***********************************************************VBScript变量命名编码规范Subtype         Prefix     Example Boolean         bln         blnFound Byte         byt         bytRasterData Date (

    2022年6月16日
    25
  • mybatis返回对象_存储过程不能返回结果

    mybatis返回对象_存储过程不能返回结果论MyBatis返回结果集_返回实体类还是Map在更多的了解mybatis后发现不单单通过实体类可以直接返回数据,还可以直接返回一个Map结果集(resultType="java.util.Map"),如果是多条数据则返回一个List&lt;Map&lt;String,Object&gt;&gt;结果集。很多人会觉得发现,直接返回一个Map的话太方便了,什么映射什么的全都不用管,只用在sql书…

    2022年10月4日
    0
  • Java 接口

    Java 接口

    2021年9月10日
    51
  • 打印机服务器显示未连接,解决win10打印机提示“无法连接打印机 后台处理程序未运行”的方法…

    打印机服务器显示未连接,解决win10打印机提示“无法连接打印机 后台处理程序未运行”的方法…如今大家在办公室中最常见的两样设备就数电脑和打印机了吧?办公人员对于打印机的使用是非常频繁的,每天都要使用。因此一旦打印机出现故障就会对我们的工作效率产生影响。近日有用户将电脑升级为win10之后发现自己的打印机不能正常的运行,每次点击打印之后就会出现:“无法连接到打印机,后台处理程序未运行”的提示。不知道你遇到这个故障的时候是如何解决的,若是还没有找到解决的方法可以使用下面的教程进行处理哦!方法…

    2022年5月1日
    153
  • 数据结构C语言严蔚敏版(第二版)超详细笔记附带课后习题[通俗易懂]

    数据结构C语言严蔚敏版(第二版)超详细笔记附带课后习题[通俗易懂]根据此书所做随笔笔记。一、绪论1.1、数据机构的研究内容用计算机解决实际问题时,步骤:首先分析实际问题,从中抽象出一个适当的数学模型,然后设计一个解决此数学模型的算法,最后编程,调试,测试。寻求数据模型的实质是分析问题,从中提取出计算机处理的对象,并找出这些对象之间的关系,然后用数学的语言加以描述。关键:分析问题中所用到的数据是如何组织的,研究数据之间存在什么样的关系。由于数据必须在计算机中处理,因此不能局限于数据本身的数学问题的研究,还必须考虑数据的物理结构,即数据在计算机中的存储结构。1.

    2022年6月10日
    93

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号