MFC中的AssertValid和Dump函数

MFC中的AssertValid和Dump函数本文转载自:VC调试中,AssertValid和Dump函数的应用——————————————————————————AssertValid()函数——————————————————————–

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

本文转载自:VC调试中,AssertValid和Dump函数的应用


—————————————–AssertValid()函数————————————-

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 函数的用户应注意该函数的限制。触发的断言指示对象一定有误,并且执行将暂停。但是,缺少断言只指示未找到任何问题,并不保证对象是好的。 

——————————————–Dump()函数—————————————-
当从 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/159054.html原文链接:https://javaforall.net

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


相关推荐

  • matlab初学者入门_什么一闻就能睡2小时

    matlab初学者入门_什么一闻就能睡2小时目录零基础入门matlab前言1.界面认识2.变量命名3.数据类型4.元胞数组和结构体5.矩阵操作6.程序结构7.基本绘图操作7.1.二维平面绘图7.2.三维立体绘图8.图形的保存与导出9.补充零基础入门matlab前言这篇文章很适合MATLAB的入门学习,这也是我在入门时学习的笔记。虽然说是”零基础“入门matlab,但是如果有其它编程语言基础的话,学起来自然会更轻松。特别鸣谢:B站UP主——爱研究的小阿楠1.界面认识2.变量命名注:Matlab中的注释%%独占一行的注释(有上下横线

    2025年12月6日
    8
  • 散文说python半篇——景观三元论与盖茨比的对话「建议收藏」

    散文说python半篇——景观三元论与盖茨比的对话

    2022年1月21日
    60
  • KNIME数据库扩展指南

    KNIME数据库扩展指南KNIME 数据库扩展指南介绍 KNIME 数据库扩展提供了一组 KNIME 节点 这些节点允许连接到 JDBC 兼容的数据库 这些节点位于 节点存储库 中的 数据库 类别中 您可以在其中找到许多数据库访问 操作和编写节点 数据库节点是每个 KNIMEAnalyti 安装的一部分 不需要安装任何其他的 KNIME 扩展 本指南描述了 KNIME 数据库扩展 并除其他外 展示了如何连接到数据库以及如何在数据库内部执行数据操作 外链图片转存失败 源站可能有防盗链机制 建议将图片保存下来直接上传

    2025年8月15日
    7
  • java输出结果保留两位小数,经典好文

    java输出结果保留两位小数,经典好文前言面试技巧另外开篇再说,先上面试干货吧。面试的题目并不一定有严格的顺序关系,有的是从前一个问题延伸而来,(探究的是一个知识的深度),有的是考察面试者的知识广度、有的纯粹是我想到哪里写到哪里的啦。。不要太在意哈,最近工作有点忙。基础知识RabbitMQ是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用之间共享数据,它是使用Erlang语言来编写的,并且是基于AMQP协议的;RabbitMQ高性能的原因Erlang语言在交换机的交互方面性能优秀的(Erlang语言最初在于交换机领域

    2022年7月8日
    26
  • 上海it外包公司排名_it外包公司排行榜怎么来的?

    上海it外包公司排名_it外包公司排行榜怎么来的?在我们平时上网的时候,总是看到在一些中介网站上会有一些IT外包公司排行榜,这些排行与其它行业的排行榜一样,指导着我们的选择,为我们的外包工作指出了一条相对明晰的道路。那到底这些网站上的排行准不准确呢?下面我们就为大家解析一下。1.名气和口碑。也许我们对外包行业不是很懂,但是在看其它行业如房地产,家电等与大众息息相关的产业时,就会发现但凡上榜的都是很有名气的,且口碑也很好。这就表明了排行还是比较…

    2022年6月14日
    47
  • Java XML XXE 底层防御

    Java XML XXE 底层防御JavaXML相关API是由JAXP定义了相关的XML的通用接口,常见包括DOM/SAX/STAX/XPATH的标准APIJavax.xml.parsers ->DOM/SAXJavax.xml.stream ->STAXJavax.xml.xpath  ->XPATHJavax.xml.bind  ->JAXBjavax.xml.ws

    2022年7月20日
    19

发表回复

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

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