调试和错误报告宏
这些宏提供有用的调试和跟踪工具。
名称 | 描述 |
---|---|
_ATL_DEBUG_INTERFACES | 将调用 _Module.Term 时检测到的任何接口泄漏写入输出窗口。 |
_ATL_DEBUG_QI | 将对 QueryInterface 的所有调用写入到输出窗口。 |
ATLASSERT | 执行与 C 运行时库中的 _ASSERTE 宏相同的功能。 |
ATLENSURE | 执行参数验证。 根据需要来调用 AtlThrow |
ATLTRACENOTIMPL | 向转储设备发送未实现指定功能的消息。 |
ATLTRACE | 根据指示的标志和级别向输出设备(例如调试器窗口)报告警告。 为实现向后兼容性而包含在内。 |
ATLTRACE2 | 根据指示的标志和级别向输出设备(例如调试器窗口)报告警告。 |
_ATL_DEBUG_INTERFACES
在包含任何 ATL 头文件之前定义此宏,以将组件接口上的所有 AddRef
和 Release
调用跟踪到输出窗口。
#define _ATL_DEBUG_INTERFACES
备注
出现的跟踪输出如下:
ATL: QIThunk - 2008 AddRef : Object = 0x00d81ba0 Refcount = 1 CBug - IBug
每个跟踪的第一部分始终为 ATL: QIThunk
。 接下来是标识正在使用的特定接口形式转换的值。 接口形式转换是一个对象,用于维护引用计数并提供此处使用的跟踪功能。 每次调用 QueryInterface
时都会创建一个新的接口形式转换,但对 IUnknown
接口的请求除外(在这种情况下,每次都返回相同的形式转换以符合 COM 的身份规则)。
接下来,你将看到 AddRef
或 Release
,指示调用了哪个方法。 之后,你将看到一个值,该值标识其接口引用计数已更改的对象。 跟踪的值是对象的 this
指针。
跟踪的引用计数是调用 AddRef
或 Release
之后该形式转换的引用计数。 请注意,此引用计数可能与对象的引用计数不匹配。 每个形式转换都维护自己的引用计数,以帮助你完全遵守 COM 的引用计数规则。
跟踪的最后一条信息是对象的名称以及受 AddRef
或 Release
调用影响的接口。
当服务器关闭并调用 _Module.Term
时检测到的任何接口泄漏都将记录如下:
ATL: QIThunk - 2005 LEAK : Object = 0x00d81ca0 Refcount = 1 MaxRefCount = 1 CBug - IBug
此处提供的信息直接映射到前面的跟踪语句中提供的信息,因此你可以在接口形式转换的整个生命周期中检查引用计数。 此外,你还可以看到该接口形式转换上的最大引用计数。
注意
_ATL_DEBUG_INTERFACES 可用于零售版本。
_ATL_DEBUG_QI
将对 QueryInterface
的所有调用写入到输出窗口。
#define _ATL_DEBUG_QI
备注
如果调用 QueryInterface
失败,输出窗口将显示:
接口名称 - failed
ATLASSERT
ATLASSERT 宏执行与 C 运行时库中的 _ASSERTE 宏相同的功能。
ATLASSERT(booleanExpression);
参数
booleanExpression
计算结果为零或不为零的表达式(包括指针)。
备注
在调试版本中,ATLASSERT 对 booleanExpression 求值并在结果为 false 时生成调试报告。
要求
标头:atldef.h
ATLENSURE
此宏用于验证传递给函数的参数。
ATLENSURE(booleanExpression);
ATLENSURE_THROW(booleanExpression, hr);
参数
booleanExpression
指定要测试的布尔表达式。
hr
指定要返回的错误代码。
备注
这些宏提供一种机制来检测参数的不正确用法并通知用户。
宏调用 ATLASSERT,如果条件不符,则调用 AtlThrow
。
在 ATLENSURE 情况下,则使用 E_FAIL 调用 AtlThrow
。
在 ATLENSURE_THROW 情况下,使用指定的 HRESULT 调用 AtlThrow
。
ATLENSURE 和 ATLASSERT 之间的区别在于 ATLENSURE 在发布版本和调试版本中都会引发异常。
示例
void MyImportantFunction(char* psz)
{
ATLENSURE(NULL != psz);
char mysz[64];
strcpy_s(mysz, sizeof(mysz), psz);
}
要求
标头: afx.h
ATLTRACENOTIMPL
在 ATL 的调试版本中,将字符串“funcname is not implemented”发送到转储设备并返回 E_NOTIMPL。
ATLTRACENOTIMPL(funcname);
参数
funcname
[in] 包含未实现的函数名称的字符串。
备注
在发布版本中,只返回 E_NOTIMPL。
示例
ATLTRACENOTIMPL(_T("IOleControl::GetControlInfo"));
要求
头:atltrace.h
ATLTRACE
根据指示的标志和级别向输出设备(例如调试器窗口)报告警告。 为实现向后兼容性而包含在内。
ATLTRACE(exp);
ATLTRACE(
DWORD category,
UINT level,
LPCSTR lpszFormat, ...);
参数
exp
[in] 要发送到输出窗口或捕获这些消息的任何应用程序的字符串和变量。
category
[in] 要报告的事件或方法的类型。 有关类别列表,请参阅备注。
level
[in] 要报告的跟踪级别。 有关详细信息,请参见备注。
lpszFormat
[in] 要发送到转储设备的格式化字符串。
备注
有关 ATLTRACE 的说明,请参阅 ATLTRACE2。 ATLTRACE 和 ATLTRACE2 行为相同,包括 ATLTRACE 是为了向后兼容。
ATLTRACE2
根据指示的标志和级别向输出设备(例如调试器窗口)报告警告。
ATLTRACE2(exp);
ATLTRACE2(
DWORD category,
UINT level,
LPCSTR lpszFormat, ...);
参数
exp
[in] 要发送到输出窗口或捕获这些消息的任何应用程序的字符串。
category
[in] 要报告的事件或方法的类型。 有关类别列表,请参阅备注。
level
[in] 要报告的跟踪级别。 有关详细信息,请参见备注。
lpszFormat
[in] 用于创建要发送到转储设备的字符串的 printf
样式格式字符串。
注解
ATLTRACE2 的缩写形式将字符串写入调试器的输出窗口。 ATLTRACE2 的第二种形式也将输出写入调试器的输出窗口,但受制于 ATL/MFC 跟踪工具的设置(请参阅 ATLTraceTool 示例)。 例如,如果你将 level 设置为 4 并将“ATL/MFC 跟踪工具”设置为级别 0,则不会看到该消息。 level 的值可以是 0、1、2、3 或 4。 默认值为 0,仅报告最严重的问题。
category 参数列出要设置的跟踪标志。 这些标志对应于你要报告的方法类型。 下表列出了可用于 category 参数的有效跟踪标志。
ATL 跟踪标志
ATL 类别 | 说明 |
---|---|
atlTraceGeneral |
报告所有 ATL 应用程序。 默认值。 |
atlTraceCOM |
有关 COM 方法的报告。 |
atlTraceQI |
有关 QueryInterface 调用的报告。 |
atlTraceRegistrar |
有关对象注册的报告。 |
atlTraceRefcount |
有关更改引用计数的报告。 |
atlTraceWindowing |
Windows 方法报告;例如,报告无效的消息映射 ID。 |
atlTraceControls |
有关控件的报告;例如,当控件或其窗口被销毁时报告。 |
atlTraceHosting |
报告托管消息;例如,容器中的客户端激活时报告。 |
atlTraceDBClient |
关于 OLE DB 消费者模板的报告;例如,当调用 GetData 失败时,输出可以包含 HRESULT。 |
atlTraceDBProvider |
关于 OLE DB 提供程序模板的报告;例如,报告列创建是否失败。 |
atlTraceSnapin |
MMC 管理单元应用程序的报告。 |
atlTraceNotImpl |
报告指示的功能未实现。 |
atlTraceAllocation |
报告由 atldbgmem.h 中的内存调试工具打印的消息。 |
MFC 跟踪标志
MFC 类别 | 说明 |
---|---|
traceAppMsg |
常规用途,MFC 消息。 始终建议使用。 |
traceDumpContext |
来自 CDumpContext 的消息。 |
traceWinMsg |
来自 MFC 的消息处理代码的消息。 |
traceMemory |
来自 MFC 内存管理代码的消息。 |
traceCmdRouting |
来自 MFC 的 Windows 命令路由代码的消息。 |
traceHtml |
来自 MFC 的 DHTML 对话框支持的消息。 |
traceSocket |
来自 MFC 套接字支持的消息。 |
traceOle |
来自 MFC 的 OLE 支持的消息。 |
traceDatabase |
来自 MFC 数据库支持的消息。 |
traceInternet |
来自 MFC Internet 支持的消息。 |
若要声明自定义跟踪类别,请声明 CTraceCategory
类的全局实例,如下所示:
CTraceCategory MY_CATEGORY(_T("MyCategoryName"), 1);
类别名称(此示例中为 MY_CATEGORY)是你为 category 参数指定的名称。 第一个参数是将在 ATL/MFC 跟踪工具中显示的类别名称。 第二个参数是默认跟踪级别。 此参数是可选的,默认跟踪级别为 0。
若要使用用户定义的类别:
ATLTRACE2(MY_CATEGORY, 2, _T("a message in a custom category"));
要指定要过滤跟踪消息,请将这些宏的定义插入到 Stdafx.h 中的 #include <atlbase.h>
语句之前。
或者,你可以在“属性页”对话框的预处理器指令中设置过滤器。 单击“预处理器”选项卡,然后将全局插入到“预处理器定义”编辑框中。
Atlbase.h 包含 ATLTRACE2 宏的默认定义,如果你在处理 atlbase.h 之前未定义这些符号,则将使用这些定义。
在发布版本中,ATLTRACE2 编译为 (void) 0
.
在格式化后,ATLTRACE2 将要发送到转储设备的字符串内容限制为不超过 1023 个字符。
ATLTRACE 和 ATLTRACE2 行为相同,包括 ATLTRACE 是为了向后兼容。
示例
int i = 1;
ATLTRACE2(atlTraceGeneral, 4, "Integer = %d\n", i);
// Output: 'Integer = 1'