VC的调试中,AssertValid和Dump函数的应用?? rt.在debug调试中,AssertValid和Dump 这两个函数怎么进行工作的?或者说怎么合理利用这两个函数?... 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 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 _DEBUGvoid 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 _DEBUGvoid CMyData::AssertValid( ) const{ // Call inherited AssertValid CObject::AssertValid( ); // Check validity of CMyData members ASSERT_VALID( m_pDataList ); // ...}#endifCMyData 使用 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 _DEBUGvoid 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 _DEBUGpMyPerson->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 $51A4Last Name: SmithFirst Name: AlanPhone #: 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窗口中才能看到。 C++ 请教CWnd::CreateEx问题 static控件调整字体大小后,字大了,但控件大小不变,字只显示出半部 关于keyboardproc()回调函数lparam参数的疑问 如何通过user32.dll 或者winapi 得到context menu 的句柄? 求这样一个“类”……在线等,谢谢 命令行参数能不能用竖线 分隔(在线) 请哪位大侠帮我看看这个问题,不甚感激!!! 请教一个问题:在“控制面板”的“管理工具”的“组件服务”中增加一个组件,这样子的用途是什么?有什么好处? 关于密码学的学习问题 DLL指针传递问题. [请问]如何添加提示信息
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 函数的用户应注意该函数的限制。触发的断言指示对象一定有误,并且执行将暂停。但是,缺少断言只指示未找到任何问题,并不保证对象是好的。
{
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 $51A4Last Name: Smith
First Name: Alan
Phone #: 581-0215{1} strcore.cpp(80) : non-object block at $00A7516E, 25 bytes long
大多数行开始处的大括号中的数字指定对象的分配顺序。最近分配的对象具有最高编号,并显示在转储的顶部。
如AssertValid(t==0);//用来判断t是否等于0,如果t!=0则终止程序
Dump函数一般用来显示debug信息的,其函数中的内容一般在debug时,在debug窗口中才能看到。