转自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. SG函数学(hua)习(shui)记录

    ---恢复内容开始--- 听说有一个东西叫SG函数 觉得自己好像原来是懂一些粗浅的应用但现在感觉要再深♂入一点呢 让我们先来介绍一下SG函数吧 这是某类满足下列条件的玄学博弈问题解法 双人.回合制: ...

  2. php数字补零的两种方法

    在php中有两个函数——至少有两个是否有其他的我还不知道,能够实现数字补零,str_pad(),sprintf()详细如下 str_pad顾名思义这个函数是针对字符串来说的这个可以对指定的字符串填补任 ...

  3. PHP 字符串两边填充补零

    str_pad顾名思义这个函数是针对字符串来说的这个可以对指定的字符串填补任何其它的字符串 例如:str_pad(带填补的字符串,填补后的长度,填补字符串,填补位置) 其中填补后的长度必须是个正整数, ...

  4. 关于Python 中的 if 语句

    学习Python,最开始我们都是先从函数学起,Python教程中有很多函数,if算是其中之一. 可能最为人所熟知的编程语句就是 if 语句了.例如: >>> >>> ...

  5. R 常用清洗函数汇总

    目录 1.which() 2.unique() 3.dplyr包 select() filter() arrange() group_by() mutate() transmutate() summa ...

  6. 一些对数学领域及数学研究的个人看法(转载自博士论坛wcboy)

    转自:http://www.math.org.cn/forum.php?mod=viewthread&tid=14819&extra=&page=1 原作者: wcboy 现在 ...

  7. MATLAB函数表(转自:http://bbs.06climate.com/forum.php?mod=viewthread&tid=16041&extra=page%3D4)

    MATLAB函数表 4.1.1特殊变量与常数 ans 计算结果的变量名 computer 确定运行的计算机 eps 浮点相对精度 Inf 无穷大 I 虚数单位 inputname 输入参数名 NaN ...

  8. 第二天:python的函 数、循环和条件、类

    https://uqer.io/community/share/54c8af17f9f06c276f651a54 第一天学习了Python的基本操作,以及几种主要的容器类型,今天学习python的函数 ...

  9. 图灵数学·统计学丛书.PDF(53本全)

    图灵数学·统计学丛书01-概率论及其应用(第1卷·第3版)-[美]William.Feller-人民邮电出版社.pdf 图灵数学·统计学丛书01-金融数学:衍生产品定价引论-[英]M·巴克斯特& ...

随机推荐

  1. c++,public/protected/private权限修饰符

    1.public的变量可以在类中以及外部访问到: 2. private只可以在类/友元中访问到. #include <iostream> using namespace std; //-- ...

  2. BZOJ 1597: [Usaco2008 Mar]土地购买( dp + 斜率优化 )

    既然每块都要买, 那么一块土地被另一块包含就可以不考虑. 先按长排序, 去掉不考虑的土地, 剩下的土地长x递增, 宽y递减 dp(v) = min{ dp(p)+xv*yp+1 } 假设dp(v)由i ...

  3. 浙江大学2015年校赛F题 ZOJ 3865 Superbot BFS 搜索

    不知道为什么比赛的时候一直想着用DFS 来写 一直想剪枝结果还是TLE = = 这题数据量不大,又是问最优解,那么一般来说是用 BFS 来写 int commandi[4] = {1, 2, 3, 4 ...

  4. 【引用】Linux 内核驱动--多点触摸接口

    本文转载自James<Linux 内核驱动--多点触摸接口>   译自:linux-2.6.31.14\Documentation\input\multi-touch-protocol.t ...

  5. (step8.2.2)hdu 2509(Be the Winner——简单博弈)

    题目大意:输入一个整数n,表示火柴堆数(原题其实指的是苹果堆数,但是为了尽量与模板保持一致,所以在这里理解为火柴堆数....其实理解为什么都没关系, 重要的是,理解就行....).在接下来的一行中,有 ...

  6. 基于visual Studio2013解决算法导论之042单源最短路径

     题目 单源最短路径 解决代码及点评 // 26单源最短路径bellmanford.cpp : 定义控制台应用程序的入口点. // #include <iostream> #incl ...

  7. CString——Left、Right、Find、ReverseFind

    CString--Left.Right.Find.ReverseFind http://hi.baidu.com/shawmar/item/08b30afb0f32d46f3c1485ec CStri ...

  8. android Listview,gridview局部刷新,部分刷新

    众所周知Listview和Gridview的刷新界面的方式是调用adapter.notifyDataSetChanged()进行界面刷新. 但是此方法有其弊端,他是将界面中的数据全部刷新一遍,不论数据 ...

  9. 再造 “手机QQ” 侧滑菜单(三)——视图联动

    代码示例:https://github.com/johnlui/SwiftSideslipLikeQQ 本 文中,我们将一起使用 UINavigationController 来管理主视图,并实现点击 ...

  10. BZOJ 1475: 方格取数( 网络流 )

    本来想写道水题....结果调了这么久!就是一个 define 里面少加了个括号 ! 二分图最大点权独立集...黑白染色一下 , 然后建图 : S -> black_node , white_no ...