_ASSERT
、_ASSERTE
、_ASSERT_EXPR
宏
计算表达式,并在结果是 false
时生成调试报告(仅限调试版本)。
语法
// Typical usage:
_ASSERT_EXPR( booleanExpression, message );
_ASSERT( booleanExpression );
_ASSERTE( booleanExpression );
参数
booleanExpression
计算结果不为零 (true
) 或为零 (false
) 的标量表达式(包括指针表达式)。
message
要显示为报告一部分的宽字符串。
备注
_ASSERT_EXPR
、 _ASSERT
和 _ASSERTE
宏为应用程序提供了一种简洁明了的机制,用于在调试过程中检查假设。 它们非常灵活,因为无需包含在 #ifdef
语句中,可防止在零售版本的应用程序中调用它们。 这种灵活性使用 _DEBUG
宏来实现。 _ASSERT_EXPR
、 _ASSERT
和 _ASSERTE
仅当在编译时定义 _DEBUG
时才可用。 未定义 _DEBUG
时,会在预处理过程中删除对这些宏的调用。
_ASSERT_EXPR
、_ASSERT
和 _ASSERTE
会计算其 booleanExpression
参数,在结果为 false
(0) 时,它们会输出诊断消息并调用 _CrtDbgReportW
以生成调试报告。 _ASSERT
宏会输出简单的诊断消息,_ASSERTE
会在消息中包含失败表达式的字符串表示形式,而 _ASSERT_EXPR
会在诊断消息中包含 message
字符串。 这些宏在 booleanExpression
的计算结果不为零时不执行任何操作。
_ASSERT_EXPR
、 _ASSERT
和 _ASSERTE
会调用 _CrtDbgReportW
,这会使所有输出都采用宽字符。 _ASSERTE
可在 booleanExpression
中正确打印 Unicode 字符, _ASSERT_EXPR
可在 message
中打印 Unicode 字符。
因为 _ASSERTE
宏会指定失败表达式,并且 _ASSERT_EXPR
允许你在生成的报告指定消息,所以它们使用户可以识别问题,而不会引用应用程序源代码。 但是存在一个缺点,即 message
打印的每个 _ASSERT_EXPR
和 _ASSERTE
计算的每个表达式都以字符串常量的形式包含在应用程序的输出(调试版本)文件中。 因此,如果对 _ASSERT_EXPR
或 _ASSERTE
进行大量调用,则这些表达式可能会大大增加输出文件的大小。
除非使用 _CrtSetReportMode
和 _CrtSetReportFile
函数另行指定,否则消息会出现在弹出对话框中,这等于设置以下内容:
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_WNDW);
_CrtDbgReportW
会基于当前报告模式以及为 _CRT_ASSERT
报告类型定义的文件,生成调试报告并确定一个或多个目标。 默认情况下,断言失败和错误会定向到调试消息窗口。 _CrtSetReportMode
和 _CrtSetReportFile
函数用于为每种报告类型定义目标。
当目标是调试消息窗口并且用户选择“重试”按钮时,如果启用了即时 (JIT) 调试,则 _CrtDbgReportW
返回 1,从而使 _ASSERT_EXPR
、_ASSERT
和 _ASSERTE
宏启动调试器。
有关报告过程的详细信息,请参阅 _CrtDbgReport
、_CrtDbgReportW
函数。 有关解决断言失败以及将这些宏用作调试错误处理机制的详细信息,请参阅用于报告的宏。
除了 _ASSERT
宏之外,assert
宏可以用于验证程序逻辑。 此宏可在这些库的调试和发布版本中使用。 _RPT
、_RPTF
调试宏还可用于生成调试报告,但它们不计算表达式。 _RPT
宏会生成简单报告。 _RPTF
宏会在生成的报告中包含源文件以及调用报告宏的位置处的行号。 提供了这些宏的宽字符版本(_RPTW
、 _RPTFW
)。 宽字符版本与窄字符版本相同,只不过宽字符字符串用于所有字符串参数和输出。
虽然 _ASSERT_EXPR
、_ASSERT
和 _ASSERTE
是宏并且可通过包含 <crtdbg.h>
来使用,但是在定义 _DEBUG
时,应用程序必须与 C 运行时库的调试版本链接,因为这些宏调用其他运行时函数。
要求
宏 | 必需的标头 |
---|---|
.- . | <crtdbg.h> |
示例
在此程序中,对 _ASSERT
和 _ASSERTE
宏进行调用以测试条件 string1 == string2
。 如果条件失败,则这些宏会打印诊断消息。 此程序中还会执行 _RPT
和 _RPTF
宏组,以作为 printf
函数的替代方法。
// crt_ASSERT_macro.c
// compile with: /D_DEBUG /MTd /Od /Zi /link /verbose:lib /debug
//
// This program uses the _ASSERT and _ASSERTE debugging macros.
//
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <crtdbg.h>
int main()
{
char *p1, *p2;
// The Reporting Mode and File must be specified
// before generating a debug report via an assert
// or report macro.
// This program sends all report types to STDOUT.
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
// Allocate and assign the pointer variables.
p1 = (char *)malloc(10);
strcpy_s(p1, 10, "I am p1");
p2 = (char *)malloc(10);
strcpy_s(p2, 10, "I am p2");
// Use the report macros as a debugging
// warning mechanism, similar to printf.
// Use the assert macros to check if the
// p1 and p2 variables are equivalent.
// If the expression fails, _ASSERTE will
// include a string representation of the
// failed expression in the report.
// _ASSERT does not include the
// expression in the generated report.
_RPT0(_CRT_WARN,
"Use the assert macros to evaluate the expression p1 == p2.\n");
_RPTF2(_CRT_WARN, "\n Will _ASSERT find '%s' == '%s' ?\n", p1, p2);
_ASSERT(p1 == p2);
_RPTF2(_CRT_WARN, "\n\n Will _ASSERTE find '%s' == '%s' ?\n",
p1, p2);
_ASSERTE(p1 == p2);
_RPT2(_CRT_ERROR, "'%s' != '%s'\n", p1, p2);
free(p2);
free(p1);
return 0;
}
Use the assert macros to evaluate the expression p1 == p2.
crt_ASSERT_macro.c(54) :
Will _ASSERT find 'I am p1' == 'I am p2' ?
crt_ASSERT_macro.c(55) : Assertion failed!
crt_ASSERT_macro.c(58) :
Will _ASSERTE find 'I am p1' == 'I am p2' ?
crt_ASSERT_macro.c(59) : Assertion failed: p1 == p2
'I am p1' != 'I am p2'