assert(编程术语)

assert(编程术语)

编写代码时,咱们老是会作出一些假设,断言就是用于在代码中捕捉这些假设,能够将断言看做是 异常处理的一种高级形式。断言表示为一些 布尔表达式,程序员相信在程序中的某个特定点该表达式值为真。能够在任什么时候候启用和禁用断言验证,所以能够在测试时启用断言,而在部署时禁用断言。一样,程序投入运行后,最终用户在遇到问题时能够从新起用断言。
中文名
assert
前置条件断言
代码执行以前必须具有的特性
解    释
维护,坚持;主张拥有等
注    意
assert是宏,而不是函数
使用断言能够建立更稳定,品质更好且不易于出错的代码。当须要在一个值为FALSE时中断当前操做的话,可使用断言。 单元测试必须使用断言(Junit/JunitX)。
除了类型检查和单元测试外,断言还提供了一种肯定各类特性是否在程序中获得维护的极好的方法。
使用断言使咱们向按契约式设计更近了一步。

断言特性

编辑
前置条件断言:代码执行以前必须具有的特性
后置条件断言:代码执行以后必须具有的特性
先后不变断言:代码执行先后不能变化的特性

使用方式

编辑
断言能够有两种形式
1.assert Expression1
2.assert Expression1:Expression2
其中Expression1应该老是一个布尔值,Expression2 是断言失败时输出的失败消息的字符串。若是Expression1为假,则抛出一个 AssertionError,这是一个错误,而不是一个异常,也就是说是一个不可控制异常(unchecked Exception),AssertionError因为是错误,因此能够不捕获,但不推荐这样作,由于那样会使你的系统进入不稳定状态。

java断言

编辑
断言在默认状况下是关闭的,要在编译时启用断言,须要使用source1.4标记 即javac source1.4 Test.java ,在运行时启用断言须要使用 -ea参数 。要在系统类中启用和禁用断言可使用 -ea和 -dsa参数。
例如:
1
2
3
4
5
6
7
8
9
public  class  AssertExampleOne{
     public  AssertExampleOne(){}
     public  static  void  main(String args[]){
         int  x= 10 ;
         System.out.println( "Testing Assertion that x==100" );
         assert  x== 100 : "Out assertion failed!" ;
         System.out.println( "Test passed!" );
     }
}
若是编译时未加 -source1.4,则编译通不过
在执行时未加 -ea 时输出为
Testing Assertion that x==100
Test passed!
jre忽略了断言的旧代码,而使用了该参数就会输出为
Testing Assertion that x==100
Exception in thread "main" java.lang.AssertionError: Out assertion failed!
at AssertExampleOne.main(AssertExampleOne.java:6)
断言的反作用
因为程序员的问题,断言的使用可能会带来反作用 ,例如:
boolean isEnable=false;
//...
  assert isEnable=true;
这个断言的反作用是由于它修改了程序中变量的值而且未抛出错误,这样的错误若是不细心的检查是很难发现的。可是同时咱们能够根据以上的反作用获得一个有用的特性,根据它来测试断言是否打开。
1
2
3
4
5
6
7
8
9
10
public  class  AssertExampleTwo{
     public  static  void  main(String args[]){
         boolean  isEnable= false ;
         //...
         assert  isEnable= true ;
         if (isEnable== false ){
             throw  newRuntimeException( "Assertion should be enable!" );
         }
     }
}

使用断言

编辑
1.能够在预计正常状况下程序不会到达的地方放置断言 :assert false
2.断言能够用于检查传递给私有方法的参数。(对于公有方法,由于是提供给外部的接口,因此必须在方法中有相应的参数检验才能保证代码的健壮性)
3.使用断言测试方法执行的前置条件和后置条件
4.使用断言检查类的不变状态,确保任何状况下,某个变量的状态必须知足。(如age属性应大于0小于某个合适值)
不用断言
断言语句不是永远会执行,能够屏蔽也能够启用
所以:
1.不要使用断言做为公共方法的参数检查,公共方法的参数永远都要执行
2.断言语句不能够有任何边界效应,不要使用断言语句去修改变量和改变方法的返回值.
C里的宏
宏名: assert
功 能: 测试一个条件并可能使程序终止
用 法: void assert(int test);
程序例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>
struct  ITEM
{
     int  key;
     int  value;
};
/*add item to list,make sure list is not null*/
void  additem( struct  ITEM* itemptr)
{
     assert (itemptr!=NULL);
     /*additemtolist*/
}
int  main( void )
{
     additem(NULL);
     return  0;
}
assert() 宏用法
注意:assert是宏,而不是函数。在C的 assert.h头文件中。
assert宏的原型定义在<assert.h>中,其做用是若是它的条件返回错误,则终止程序执行,原型定义:
1
2
3
4
5
6
#defineassert(expr)\
((expr)\
?__ASSERT_VOID_CAST(0)\
:__assert_fail(__STRING(expr),__FILE__,__LINE__,__ASSERT_FUNCTION))
 
/*DefinedInGlibc2.15*/
assert的做用是先计算表达式 expr, 若是其值为假(即为0),那么它会打印出来assert的内容和__FILE__, __LINE__, __ASSERT_FUNCTION,而后执行abort()函数使kernel杀掉本身并coredump(是否生成coredump文件,取决于系统 配置);不然,assert()无任何做用。宏assert()通常用于确认程序的正常操做,其中表达式构造无错时才为真值。完成调试后,没必要从源代码中 删除assert()语句,由于宏NDEBUG有定义时,宏assert()的定义为空。 [1]  
请看下面的程序清单badptr.c:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
int  main( void ){
     FILE * fp;
     fp= fopen ( "test.txt" , "w" ); //以可写的方式打开一个文件,若是不存在就建立一个同名文件
     assert (fp); //因此这里不会出错
     fclose (fp);
     fp= fopen ( "noexitfile.txt" , "r" ); //以只读的方式打开一个文件,若是不存在就打开文件失败
     assert (fp); //因此这里出错
     fclose (fp); //程序永远都执行不到这里来
     return  0;
}
[root@localhost error_process]# gcc badptr.c
[root@localhost error_process]# ./a.out
a.out: badptr.c:14: main: Assertion `fp' failed.
若是使用动态连接libc,那么除了__FILE__, __LINE__, __ASSERT_FUNCTION会让目标变的稍稍大了一点,并不会由于屡次使用assert()增长目标不少。不过好处也很明显,就是会在 assert的地方会打印出来文件名,行数,和函数名。另外,要注意用assert()的错误程度。若是assert()的条件fail了,那么会调用 abort()函数让kernel杀掉本身,哪怕用户本身从新注册了SIGABRT信号的行为(abort()会先向本身发送信号SIGABRT保证用户 的handler正确执行,而后修改SIGABRT信号的行为为默认行为coredump,再次像本身发送SIGABRT,coredump)。
在调试结束后,能够经过在包含#include <assert.h>的语句以前插入 #define NDEBUG 来禁用assert调用,示例代码以下:
#include <stdio.h>
#define NDEBUG
#include <assert.h>
用法总结与注意事项:
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不能代替条件过滤
注意:当对于浮点数:
#include<assert.h>
float pi=3.14f;
assert (pi==3.14f);
在switch语句中老是要有default子句来显示信息(Assert)。
int number = SomeMethod();
switch(number){
case 1: Trace.WriteLine("Case 1:");
break;
case 2: Trace.WriteLine("Case 2:");
break;
default : Debug.Assert(false);
break;
}
相关文章
相关标签/搜索