我一直在研究OpenCV教程并遇到了assert
函数;它做了什么?
答案 0 :(得分:267)
assert
将终止程序(通常使用引用assert语句的消息),如果其参数结果为false。它通常在调试期间用于在发生意外情况时使程序更加明显失败。
例如:
assert(length >= 0); // die if length is negative.
如果失败,您还可以添加更多信息,以便显示:
assert(length >= 0 && "Whoops, length can't possibly be negative! (didn't we just check 10 lines ago?) Tell jsmith");
或者像这样:
assert(("Length can't possibly be negative! Tell jsmith", length >= 0));
当您进行发布(非调试)构建时,您还可以通过定义assert
宏(通常使用编译器开关)来消除评估NDEBUG
语句的开销。这样做的必然结果是你的程序永远不会依赖于运行的断言宏。
// BAD
assert(x++);
// GOOD
assert(x);
x++;
// Watch out! Depends on the function:
assert(foo());
// Here's a safer way:
int ret = foo();
assert(ret);
从调用abort()的程序和不保证执行任何操作的组合中,断言应仅用于测试开发人员所假设的内容,而不是用户输入数字而不是字母(应该通过其他方式处理)。
答案 1 :(得分:104)
断言计算机声明类似于英语中确保的声明。
答案 2 :(得分:13)
看看
assert() example program in C++
许多编译器都提供了一个断言() 宏。 assert()宏返回TRUE 如果它的参数计算为TRUE和 如果它采取某种行动 评估错误。许多编译器都会 在断言()上中止该程序 失败;其他人会抛出异常
断言()的一个强大功能 宏是那个预处理器 如果将它折叠成没有代码的话 DEBUG没有定义。这太好了 在开发过程中提供帮助的时候 最终产品船没有 绩效惩罚也没有增加 可执行版本的大小 该计划。
例如
#include <stdio.h>
#include <assert.h>
void analyze (char *, int);
int main(void)
{
char *string = "ABC";
int length = 3;
analyze(string, length);
printf("The string %s is not null or empty, "
"and has length %d \n", string, length);
}
void analyze(char *string, int length)
{
assert(string != NULL); /* cannot be NULL */
assert(*string != '\0'); /* cannot be empty */
assert(length > 0); /* must be positive */
}
/**************** Output should be similar to ******************
The string ABC is not null or empty, and has length 3
答案 3 :(得分:6)
assert()函数可以诊断程序错误。它在<assert.h>
中定义,其原型是
void assert(int expression);
参数表达式可以是您要测试的任何内容 - 变量或任何C表达式。如果expression的计算结果为TRUE,则assert()不执行任何操作。如果expression的计算结果为FALSE,则assert()会在stderr上显示错误消息并中止程序执行。
你如何使用assert()?它最常用于追踪程序错误(与编译错误不同)。错误不会阻止程序编译,但会导致程序输出错误或运行不正确(例如锁定)。例如,您正在编写的财务分析程序可能偶尔会给出错误的答案。你怀疑这个问题是由变量interest_rate带来负值引起的,这个值应该永远不会发生。要检查这一点,请放置语句
断言(interest_rate&gt; = 0); 在程序中使用interest_rate的位置。如果变量确实变为负数,则assert()宏会提醒您。然后,您可以检查相关代码以找出问题的原因。
要了解assert()的工作原理,请运行下面的示例程序。如果输入非零值,程序将显示该值并正常终止。如果输入零,则assert()宏会强制程序异常终止。您看到的确切错误消息将取决于您的编译器,但这是一个典型示例:
断言失败:x,文件列表19_3.c,第13行 请注意,为了使assert()起作用,必须在调试模式下编译程序。有关启用调试模式的信息,请参阅编译器文档(如稍后所述)。当您稍后在发布模式下编译最终版本时,将禁用assert()宏。
int x;
printf("\nEnter an integer value: ");
scanf("%d", &x);
assert(x >= 0);
printf("You entered %d.\n", x);
return(0);
输入一个整数值:10
你输了10。
输入一个整数值:-1
错误讯息: 异常程序终止
您的错误消息可能会有所不同,具体取决于您的系统和编译器,但总体思路是相同的。
答案 4 :(得分:4)
对于大多数编译器来说,像'引发异常'和'暂停执行'这样的东西可能都是如此,但对所有编译器都不是。 (顺便说一句,是否存在真正抛出异常的断言语句?)
这是c6x和其他TI编译器使用的断言的一个有趣的,稍微不同的含义:在看到某些断言语句时,这些编译器使用该语句中的信息来执行某些优化。恶
C:
中的示例int dot_product(short *x, short *y, short z)
{
int sum = 0
int i;
assert( ( (int)(x) & 0x3 ) == 0 );
assert( ( (int)(y) & 0x3 ) == 0 );
for( i = 0 ; i < z ; ++i )
sum += x[ i ] * y[ i ];
return sum;
}
这告诉de编译器数组在32位边界上对齐,因此编译器可以为这种对齐生成特定的指令。
答案 5 :(得分:1)
C ++ 11 N3337标准草案
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
19.3断言
1(表42)中描述的标题&lt; cassert&gt;提供了一个用于记录C ++程序断言的宏 以及禁用断言检查的机制。
2内容与标准C库标题&lt; assert.h&gt;相同。
C99 N1256标准草案
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
7.2诊断&lt; assert.h&gt;
1标题
<assert.h>
定义断言宏,并引用另一个宏NDEBUG
,它不是由<assert.h>
定义的。如果NDEBUG
被定义为宏名称 在源文件中指向&lt; assert.h&gt;包含,断言宏简单定义为#define assert(ignore) ((void)0)
每次根据NDEBUG的当前状态重新定义断言宏
<assert.h>
已包含在内。2。 断言宏应实现为宏,而不是实际功能。如果 为了访问实际函数,宏定义被抑制,行为是 未定义。
7.2.1程序诊断
7.2.1.1断言宏
概要
1
#include <assert.h> void assert(scalar expression);
描述
2 断言宏将诊断测试放入程序中;它扩展为void表达式。 执行时,如果表达式(应具有标量类型)为false(即, 比较等于0),断言宏写入有关特定呼叫的信息 失败(包括参数的文本,源文件的名称,源代码行 number和封闭函数的名称 - 后者分别是值的值 预处理宏
__FILE__
和__LINE__
以及标识符__func__
)在实现定义格式的标准错误流上。 165)它 然后调用中止函数。返回
3 断言宏不返回任何值。
答案 6 :(得分:0)
Assert允许您在条件(断言)为假时暂停执行。
例如(Pseudocode):
Bank myBank = Bank.GetMyStuff();
assert(myBank != NULL);
// .. Continue.
如果myBank为NULL,则该函数将停止执行,并产生错误。这非常适合使某些可重用代码接受正确的条件等。
答案 7 :(得分:0)
如果已评估的值为false,则该函数将暂停程序执行。通常它被宏包围,因此在使用发布设置进行编译时不会将其编译为结果二进制文件。
它旨在用于测试您所做的假设。例如:
void strcpy(char* dest, char* src){
//pointers shouldn't be null
assert(dest!=null);
assert(src!=null);
//copy string
while(*dest++ = *src++);
}
你想要的理想是你可以在你的程序中出错,比如调用一个带有无效参数的函数,然后在它出现段错误之前点击一个断言(或者无法按预期工作)
答案 8 :(得分:0)
在其他情况下使用assert()函数和printf的主要原因有三个:
assert()函数主要在调试阶段使用,每次要测试条件(甚至可能不会在最终代码中使用)时,都用printf语句编写是否麻烦。 p>
在大型软件部署中,assert非常方便,您可以在为assert()函数链接头文件之前使用定义的NDEBUG宏使编译器忽略assert语句。
assert()在您设计函数或某些代码时想要方便的使用,以使您知道什么限制代码将无法正常工作,并最终包含一个if评估(基本上是在假设条件下进行评估)的想法。
答案 9 :(得分:-4)
此外,您可以使用它来检查动态分配是否成功。
代码示例:
int ** p;
p = new int * [5]; // Dynamic array (size 5) of pointers to int
for (int i = 0; i < 5; ++i) {
p[i] = new int[3]; // Each i(ptr) is now pointing to a dynamic
// array (size 3) of actual int values
}
assert (p); // Check the dynamic allocation.
类似于:
if (p == NULL) {
cout << "dynamic allocation failed" << endl;
exit(1);
}