ASSERT断言

ASSERT断言

  编写代码时,我们总是会做出一些假设,断言就是用于在代码中捕捉这些假设,可以将断言看作是异常处理的一种高级形式。断言表示为一些布尔表达式,程序员相信在程序中的某个特定点该表达式值为真。可以在任何时候启用和禁用断言验证,因此可以在测试时启用断言,而在部署时禁用断言。同样,程序投入运行后,最终用户在遇到问题时可以重新起用断言。

  代码执行之前必须具备的特性;

  assert是宏,而不是函数;
  使用断言可以创建更稳定,品质更好且不易于出错的代码。
  断言语句不是永远会执行,可以屏蔽也可以启用。
  
1. 断言使用条件
  (1)使用断言测试方法执行的前置条件和后置条件;
  (2)可以在预计正常情况下程序不会到达的地方放置断言 :assert false
2. C语言中
  宏名: assert
  功 能: 测试一个条件并可能使程序终止
  用 法: void assert(int test);
#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>中,其作用是如果它的条件返回错误,则终止程序执行,原型定义

#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()的定义为空。

#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;
}

  在调试结束后,可以通过在包含#include <assert.h>的语句之前插入

  #define NDEBUG //来禁用assert调用

#include <stdio.h>
#define NDEBUG
#include <assert.h>

3. 用法总结与注意事项

  (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;
}

4. C++中的用法

   void assert(  int expression ); 

  参数:Expression (including pointers) that evaluates to nonzero or 0.(表达式【包括指针】是非零或零)
  原理:assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。

 1 // crt_assert.c
 2 // compile with: /c
 3 #include <stdio.h>
 4 #include <assert.h>
 5 #include <string.h>
 6
 7 void analyze_string( char *string );   // Prototype
 8
 9 int main( void )
10 {
11    char  test1[] = "abc", *test2 = NULL, test3[] = "";
12
13    printf ( "Analyzing string ‘%s‘\n", test1 ); fflush( stdout );
14    analyze_string( test1 );
15    printf ( "Analyzing string ‘%s‘\n", test2 ); fflush( stdout );
16    analyze_string( test2 );
17    printf ( "Analyzing string ‘%s‘\n", test3 ); fflush( stdout );
18    analyze_string( test3 );
19 }
20
21 // Tests a string to see if it is NULL,
22 // empty, or longer than 0 characters.
23 void analyze_string( char * string )
24 {
25    assert( string != NULL );        // Cannot be NULL
26    assert( *string != ‘\0‘ );       // Cannot be empty
27    assert( strlen( string ) > 2 );  // Length must exceed 2
28 } 

  输出:

    Analyzing string ‘abc‘
    Analyzing string ‘(null)‘
    Assertion failed: string != NULL, file assert.cpp, line 25
    abnormal program termination  

  加入#define NDEBUG之后,上文第一个例子输出结果为:

#include <stdio.h>
#define NDEBUG
#include <assert.h>

  添加 #define NDEBUG后输出如下:

    Analyzing string ‘abc‘
    Analyzing string ‘(null)‘
    Analyzing string ‘‘  

5. C++例子

  在面试中经常用到的一个题目:
  已知memcpy的函数为:

  void* memcpy(void *dest , const void* src , size_t count)

  其中dest是目的指针,src是源指针。不调用c++/c的memcpy库函数,请编写memcpy。

    void* memcpy(void *dst, const void *src, size_t count)
    {
        //安全检查
        assert( (dst != NULL) && (src != NULL) );      

        unsigned char *pdst = (unsigned char *)dst;
        const unsigned char *psrc = (const unsigned char *)src;      

        //防止内存重复
        assert(!(psrc<=pdst && pdst<psrc+count));
        assert(!(pdst<=psrc && psrc<pdst+count));      

        while(count--)
        {
            *pdst = *psrc;
            pdst++;
            psrc++;
        }
        return dst;
    }    
时间: 2024-10-25 00:39:59

ASSERT断言的相关文章

Spring Assert断言工具类

Spring 中 org.springframework.util.Assert 类实现合法性检测,Assert的方法如下: 断言方法说明: 1. notNull(Object object)  当 object 不为 null 时抛出异常,notNull(Object object, String message) 方法允许您通过 message 定制异常信息.和 notNull() 方法断言规则相反的方法是 isNull(Object object)/isNull(Object object

C++ ASSERT() 断言机制

C++ ASSERT() 断言机制 ASSERT()是一个调试程序时经常使用的宏,在程序运行时它计算括号内的表达式,如果表达式为FALSE (0), 程序将报告错误,并终止执行.如果表达式不为0,则继续执行后面的语句.这个宏通常原来判断程序中是否出现了明显非法的数据,如果出现了终止程序以免导致严重后果,同时也便于查找错误. 原型定义: #include <assert.h> void assert( int expression_r_r_r ); assert的作用是现计算表达式 expres

Spring Assert断言 (方法入参检测工具类-断言)

Web 应用在接受表单提交的数据后都需要对其进行合法性检查,如果表单数据不合法,请求将被驳回.类似的,当我们在编写类的方法时,也常常需要对方法入参进行合 法性检查,如果入参不符合要求,方法将通过抛出异常的方式拒绝后续处理.举一个例子:有一个根据文件名获取输入流的方法:InputStream getData(String file),为了使方法能够成功执行,必须保证 file 入参不能为 null 或空白字符,否则根本无须进行后继的处理.这时方法的编写者通常会在方法体的最前面编写一段对入参进行检测

python assert断言函数

python assert断言是声明布尔值必须为真的判定,如果发生异常就说明表达式为假.可以理解assert断言语句为raise-if-not,用来测试表示式,其返回值为假,就会触发异常. self.assertEqual(a,b,msg=msg)   #判断a与.b是否一致,msg类似备注,可以为空 self.assertNotEqual(a,b,msg=msg)  #判断a与b是否不一致 self.assertTrue(a,msg=none)    #判断a是否为True self.asse

pytest自动化7:assert断言

前言:assert断言就是将实际结果和期望结果做对比,符合预期结果就测试pass,不符合预期就测试failed. 实例1:简单断言 实例1优化版--增加异常信息文字描述 异常断言 excinfo 是一个异常信息实例,它是围绕实际引发的异常的包装器.主要属性是.type. .value 和 .traceback 注意:断言type的时候,异常类型是不需要加引号的,断言value值的时候需转str ---------------------------------------------------

assert断言用法

使用assert断言是学习python一个非常好的习惯,python assert 断言句语格式及用法很简单.在没完善一个程序之前,我们不知道程序在哪里会出错,与其让它在运行最崩溃,不如在出现错误条件时就崩溃,这时候就需要assert断言的帮助.本文主要是讲assert断言的基础知识. python assert断言的作用 python assert断言是声明其布尔值必须为真的判定,如果发生异常就说明表达式为假.可以理解assert断言语句为raise-if-not,用来测试表示式,其返回值为假

Java中assert(断言)的使用

1.Eclipse中默认assert(断言)是关闭,开启方式如下: 简单来说:就是设置一下jvm的参数,参数是-enableassertions或者-ea(推荐). 2.assert格式 1.格式1 assert [boolean 表达式] 如果[boolean表达式]为true,则程序继续执行. 如果为false,则程序抛出AssertionError,并终止执行. 2.格式2 assert [boolean 表达式 : 错误表达式 (日志)] 如果[boolean表达式]为true,则程序继

assert 断言

断言表示为某些条件判断(多用逻辑语句),当需要测定或是确保在程序中表达式值为真.可以启用断言进行验证,因此可以在程序测试时启用断言,而在部署时禁用断言. 断言当遇到正确的判断和错误的判断时,会怎么响应. vim assert.c ./a.out * 当断言为假时,后续执行中断.

JavaSE assert断言的学习

在Java中,assert关键字是从JAVA SE 1.4 引入的,为了避免和老版本的Java代码中使用了assert关键字导致错误,Java在执行的时候默认是不启动断言检查的(这个时候,所有的断言语句都将忽略!),如果要开启断言检查,则需要用开关-enableassertions或-ea来开启. assert关键字语法很简单,有两种用法: 1.assert <boolean表达式> 如果<boolean表达式>为true,则程序继续执行. 如果为false,则程序抛出Assert