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

AssertValid函数学习的更多相关文章

  1. Python3中的字符串函数学习总结

    这篇文章主要介绍了Python3中的字符串函数学习总结,本文讲解了格式化类方法.查找 & 替换类方法.拆分 & 组合类方法等内容,需要的朋友可以参考下. Sequence Types ...

  2. Drools 函数学习

    Drools 函数学习 函数是定义在规则文件当中一代码块,作用是将在规则文件当中若干个规则都会用到的业务操作封装起来,实现业务代码的复用,减少规则编写的工作量.函数的编写位置可以是规则文件当中 pac ...

  3. C语言(函数)学习之strstr strcasestr

    C语言(函数)学习之[strstr]&[strcasestr]一.strstr函数使用[1]函数原型char*strstr(constchar*haystack,constchar*needl ...

  4. Java中的回调函数学习

    Java中的回调函数学习 博客分类: J2SE JavaJ#  一般来说分为以下几步: 声明回调函数的统一接口interface A,包含方法callback(); 在调用类caller内将该接口设置 ...

  5. Theano.tensor.round函数学习,同时解决输出Elemwise{xxx,no_inplace}.0的问题

    1. 出现Elemwise{xxx,no_inplace}.0   这是因为没有定义theano.function所致,参考下面错误示范: y = np.random.normal(size=(2,2 ...

  6. C++学习基础十六-- 函数学习笔记

    C++ Primer 第七章-函数学习笔记 一步一个脚印.循序渐进的学习. 一.参数传递 每次调用函数时,都会重新创建函数所有的形参,此时所传递的实参将会初始化对应的形参. 「如果形参是非引用类型,则 ...

  7. pythone函数基础(8)内置函数学习

    内置函数学习# sorted# map# filter# max# sum# round# chr# ord# dir# bool# eval# exec# zipimport mathres = m ...

  8. Javascript 随机数函数 学习之二:产生服从正态分布随机数

    一.为什么需要服从正态分布的随机函数 一般我们经常使用的随机数函数 Math.random() 产生的是服从均匀分布的随机数,能够模拟等概率出现的情况,例如 扔一个骰子,1到6点的概率应该相等,但现实 ...

  9. Javascript 随机数函数 学习之一:产生服从均匀分布随机数

    大家都知道Math.random是 javascript 中返回伪随机数的函数,但查看 MDN, The Math.random() function returns a floating-point ...

随机推荐

  1. 编写高效SQL最佳实践

    编写高效 SQL 语句的最佳实践 秦玮, 高级软件工程师, IBM 王广成, 软件工程师, IBM 王韵婷, 高级软件工程师, IBM 简介: 本文列举了一些在编写 SQL 查询语句时可能导致 DB2 ...

  2. java web 学习(1)

    java web 应用的核心技术包括以下几个方面: jsp:进行输入和输出的基本手段 javabean:完成功能的处理 servlet:对应用的流程进行控制 jdbc:是与数据库进行交互不可缺少的技术 ...

  3. Yii2的相关学习记录,alert等美化、confirm异步、session中的flash及小部件的使用(六)

    呃,系统自带的alert.confirm等弹出框实在是难看,作为一个颜控,这能忍? 这里我用的是kartik-v/yii2-dialog,这个是基于bootstrap3-dialog这个来做了一些常用 ...

  4. select 1 from table where的作用?

    "SELECT 1 FROM identity_approve WHERE identity_num=' " . trim($_POST['IDnumber']) . " ...

  5. jquery获取元素方式

    1 从集合中通过指定的序号获取元素 html: <div> <p>0</p> <p>1</p> <p>2</p> & ...

  6. jquery 节点操作大全

    $para.attr("title"); 实例: <script type="text/javascript"> //<![CDATA[ $( ...

  7. uva 10820 (筛法构造欧拉函数)

    send a table When participating in programming contests, you sometimes face the following problem: Y ...

  8. springmvc 参数绑定

    1. httpservletrequest request request.getParameter("a")方法去取参数 用注解@RequestParam绑定请求参数 用注解@R ...

  9. 重构后的程序:通过rsync命令抓取日志文件

    push.sh #!/bin/bash function push() { local ip=$ local user=$ local password=$ local path=$ local lo ...

  10. ExtJs5_继承自定义一个控件

    Extjs的开发都可以遵循OOP的原则,其对类的封装也很完善了.自定义一个控件最简单的办法就是继承一个已有的控件.根据上一节的需要,我做了一个Button的子类.首先根据目录结构,在app目录下建立一 ...