调试和错误报告宏

这些宏提供有用的调试和跟踪工具。

名称 描述
_ATL_DEBUG_INTERFACES 将调用 _Module.Term 时检测到的任何接口泄漏写入输出窗口。
_ATL_DEBUG_QI 将对 QueryInterface 的所有调用写入到输出窗口。
ATLASSERT 执行与 C 运行时库中的 _ASSERTE 宏相同的功能。
ATLENSURE 执行参数验证。 根据需要来调用 AtlThrow
ATLTRACENOTIMPL 向转储设备发送未实现指定功能的消息。
ATLTRACE 根据指示的标志和级别向输出设备(例如调试器窗口)报告警告。 为实现向后兼容性而包含在内。
ATLTRACE2 根据指示的标志和级别向输出设备(例如调试器窗口)报告警告。

_ATL_DEBUG_INTERFACES

在包含任何 ATL 头文件之前定义此宏,以将组件接口上的所有 AddRefRelease 调用跟踪到输出窗口。

#define _ATL_DEBUG_INTERFACES

备注

出现的跟踪输出如下:

ATL: QIThunk - 2008 AddRef : Object = 0x00d81ba0 Refcount = 1 CBug - IBug

每个跟踪的第一部分始终为 ATL: QIThunk。 接下来是标识正在使用的特定接口形式转换的值。 接口形式转换是一个对象,用于维护引用计数并提供此处使用的跟踪功能。 每次调用 QueryInterface 时都会创建一个新的接口形式转换,但对 IUnknown 接口的请求除外(在这种情况下,每次都返回相同的形式转换以符合 COM 的身份规则)。

接下来,你将看到 AddRefRelease,指示调用了哪个方法。 之后,你将看到一个值,该值标识其接口引用计数已更改的对象。 跟踪的值是对象的 this 指针。

跟踪的引用计数是调用 AddRefRelease 之后该形式转换的引用计数。 请注意,此引用计数可能与对象的引用计数不匹配。 每个形式转换都维护自己的引用计数,以帮助你完全遵守 COM 的引用计数规则。

跟踪的最后一条信息是对象的名称以及受 AddRefRelease 调用影响的接口。

当服务器关闭并调用 _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'

另请参阅


调试和错误报告全局函数