您的位置:首页 > 其它

assert用法

2015-10-28 21:52 260 查看
我一直以为assert仅仅是个报错函数,事实上,它居然是个宏,并且作用并非“报错”。
  在经过对其进行一定了解之后,对其作用及用法有了一定的了解,assert()的用法像是一种“契约式编程”,在我的理解中,其表达的意思就是,程序在我的假设条件下,能够正常良好的运作,其实就相当于一个if语句:
if(假设成立)
{
程序正常运行;
}
else
{
报错&&终止程序!(避免由程序运行引起更大的错误)
}
  但是这样写的话,就会有无数个if语句,甚至会出现,一个if语句的括号从文件头到文件尾,并且大多数情况下,我们要进行验证的假设,只是属于偶然性事件,又或者我们仅仅想测试一下,一些最坏情况是否发生,所以这里有了assert().
   assert宏的原型定义在assert.h中,其作用是如果它的条件返回错误,则终止程序执行.

#include "assert.h"
void assert( int expression );
  assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。
使用assert的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。
  在调试结束后,可以通过在包含#include 的语句之前插入 #define NDEBUG 来禁用assert调用,示例代码如下:

#include
#define NDEBUG
#include
  用法总结与注意事项:
  1)在函数开始处检验传入参数的合法性
  如:
  
int resetBufferSize(int nNewSize)
{
//功能:改变缓冲区大小,
//参数:nNewSize 缓冲区新长度
//返回值:缓冲区当前长度
//说明:保持原信息内容不变 nNewSize<=0表示清除缓冲区
assert(nNewSize >= 0);
assert(nNewSize <= MAX_BUFFER_SIZE);

...
}
  2)每个assert只检验一个条件,因为同时检验多个条件时,如果断言失败,无法直观的判断是哪个条件失败
  
  不好:
assert(nOffset>=0 && nOffset+nSize<=m_nInfomationSize);
 
  好:
 assert(nOffset >= 0);
 assert(nOffset+nSize <= m_nInfomationSize);
 
  3)不能使用改变环境的语句,因为assert只在DEBUG个生效,如果这么做,会使用程序在真正运行时遇到问题
  错误:
assert(i++ < 100)
这是因为如果出错,比如在执行之前i=100,那么这条语句就不会执行,那么i++这条命令就没有执行。
  正确:
assert(i < 100)
i++;
 
  4)assert和后面的语句应空一行,以形成逻辑和视觉上的一致感
  
  5)有的地方,assert不能代替条件过滤   
  
  程序一般分为Debug 版本和Release 版本,Debug 版本用于内部调试,Release 版本发行给用户使用。断言assert 是仅在Debug 版本起作用的宏,它用于检查“不应该”发生的情况。以下是一个内存复制程序,在运行过程中,如果assert 的参数为假,那么程序就会中止(一般地还会出现提示对话,说明在什么地方引发了assert)。

以下是使用断言的几个原则:
  
  (1)使用断言捕捉不应该发生的非法情况。不要混淆非法情况与错误情况之间的区别,后者是必然存在的并且是一定要作出处理的。
  
  (2)使用断言对函数的参数进行确认。
  
  (3)在编写函数时,要进行反复的考查,并且自问:“我打算做哪些假定?”一旦确定了的假定,就要使用断言对假定进行检查。
  
  (4)一般教科书都鼓励程序员们进行防错性的程序设计,但要记住这种编程风格会隐瞒错误。当进行防错性编程时,如果“不可能发生”的事情的确发生了,则要使用断言进行报警。

  ASSERT ()是一个调试程序时经常使用的宏,在程序运行时它计算括号内的表达式,如果表达式为FALSE (0), 程序将报告错误,并终止执行。如果表达式不为0,则继续执行后面的语句。这个宏通常原来判断程序中是否出现了明显非法的数据,如果出现了终止程序以免导致严重后果,同时也便于查找错误。

ASSERT只有在Debug版本中才有效,如果编译为Release版本则被忽略。

在编码时,有一个好的目标应该时刻铭记在心,那就是:应该想办法让bug或者异常错误尽早使得程序down掉,或者出现错误。因为这样可以帮助你在开发和测试阶段尽快找出bug。有一些错误不会无缘无故的暴露自己,往往是产品都到了客户手上,这些错误才会显现出来。
一个最简单的检查异常条件的方法是使用标准C的assert宏,它的参数是一个bool表达式。当表达式为假时,程序会退出。在退出之前打印错误消息,包括源文件,行号,和表达式本身。断言非常有用,它提供了一个作用于程序内部的广泛的一致性检查方法。例如,使用断言测试函数参数的有效性,测试异常的返回值等等。

每一个断言的使用不仅提供了一个程序运行时的条件检查,也像一个对源代码级别的程序操作的说明性文档。如果你的程序包含了一个断言,也就是告诉那些阅读你源代码的人,在你的源代码中,在程序的这一点,这个条件应该为真,如果不为真,那就是一个bug。
当然,在追求性能的代码中,使用assert会降低程序性能。但是你放心,在编译时加入NDEBUG参数编译器就可以对assert进行预处理,从而移除它。正因为在预处理时可能移除assert,那你使用时就得小心了。什么时候用,什么时候不用就成了一个问题。通常,你不应该在assert内部调用函数,定义变量,或者使用改变值的操作符,如++。
我们假设你这样使用了:
for (i = 0; i <= 100; ++i) assert (do_something () == 0);
然后,你可能会发现这样会使得性能大大降低,从而在创新编译使使用NDEGUG参数。这将移除整个assert宏,这就将do_something( )也被移除了,再也不被调用。为了纠正错误,你应该这样写:
for (i = 0; i <= 100; ++i) { int status = do_something (); assert (status == 0); }
另外应该铭记在心的是,不要用assert去检查无效的输入。用户可不喜欢自己在输入时程序直接退出,即便是输入错误,程序最好也有友好的响应。所以,你应该对无效输入进行检查,并输出一些有用的提示信息。只在程序运行中进行内部检查时使用断言。
在这里,我会给出一些比较好的在程序中使用assert的地方:
(1)空指针检查。例如,针对一个函数的参数进行空指针检查。你可以这样使用:
assert (pointer != NULL);
产生的错误会像这样:
Assertion ‘pointer != ((void *)0)’ failed
这样,当出现空指针时,你的程序就会退出,并很好的给出错误信息。
(2)检查函数参数的值。例如,如果一个函数只能在它的一个参数foo为正值的时候被调用,你可以在函数开始时这样写:assert (foo > 0);,这将帮助你检测函数的错误使用,这也给源代码阅读者很清晰的印象,那就是在这里对函数的参数值有限制。

ASSERT()是一个调试程序时经常使用的宏,在程序运行时它计算括号内的表达式,如果表达式为FALSE (0), 程序将报告错误,并终止执行。如果表达式不为0,则继续执行后面的语句。这个宏通常原来判断程序中是否出现了明显非法的数据,如果出现了终止程序以免导致严重后果,同时也便于查找错误。

---------------------------------------------------------------

ASSERT宏定义如下

#define  ASSERT(f)  \
do  \
{  \
if  (!(f)  &&  AfxAssertFailedLine(THIS_FILE,  __LINE__))  \
AfxDebugBreak();  \
}  while  (0)  \
ASSERT(逻辑表达式)

如果括号中的逻辑表达式值为假的话,会弹出调试命令窗口,提示具体在哪个文件的哪一行发生了断言错误!
---------------------------------------------------------------
---------------------------------------------------------------
ASSERT
Evaluates an expression, and displays a diagnostic message if the expression is FALSE. Ignored in retail builds.
Syntax

ASSERT(
cond
);

Parameters

cond

Expression to evaluate.

Remarks

In debug builds, if the expression is FALSE, this macro displays a message box with the text of the expression, the name of the source file, and the line number. The user can ignore the assertion, enter the debugger, or quit the application.

Example

ASSERT(rtStartTime <= rtEndTime);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: