• C语言_断言assert详解


    一、assert定义

    assert() 的用法像是一种"契约式编程",在我的理解中,其表达的意思就是,程序在我的假设条件下,能够正常良好的运作,其实就相当于一个 if 语句:

    1. if(假设成立)
    2. {
    3.      程序正常运行;
    4. }
    5. else
    6. {
    7.       报错&&终止程序!(避免由程序运行引起更大的错误)  
    8. }

    但是这样写的话,就会有无数个 if 语句,甚至会出现,一个 if 语句的括号从文件头到文件尾,并且大多数情况下,我们要进行验证的假设,只是属于偶然性事件,又或者我们仅仅想测试一下,一些最坏情况是否发生,所以这里有了 assert()

    assert 宏的原型定义在 assert.h 中,其作用是如果它的条件返回错误,则终止程序执行。

    1. #include "assert.h" 
    2. void assert( int expression );

    assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。

    程序badptr.c:

    1. #include
    2. #include
    3. #include
    4. int main( void ){undefined
    5. FILE *fp;
    6. fp = fopen( "test.txt", "w" );//以可写的方式打开一个文件,如果不存在就创建一个同名文件
    7. assert( fp ); //所以这里不会出错
    8. fclose( fp );
    9. fp = fopen( "noexitfile.txt", "r" );//以只读的方式打开一个文件,如果不存在就打开文件失败
    10. assert( fp ); //所以这里出错
    11. fclose( fp ); //程序永远都执行不到这里来
    12. return 0;
    13. }

    [root@localhost error_process]# gcc badptr.c
    [root@localhost error_process]# ./a.out
    a.out: badptr.c:14: main: Assertion `fp’ failed.

    使用assert的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。
    在调试结束后,可以通过在包含#include 的语句之前插入 #define NDEBUG 来禁用assert调用:

    1. #include
    2. #define NDEBUG
    3. #include

    二、用法总结与注意事项

     1、在函数开始处检验传入参数的合法性

    1. int resetBufferSize(int nNewSize)
    2. {
    3. //功能:改变缓冲区大小,
    4. //参数:nNewSize 缓冲区新长度
    5. //返回值:缓冲区当前长度
    6. //说明:保持原信息内容不变 nNewSize<=0表示清除缓冲区
    7. assert(nNewSize >= 0);
    8. assert(nNewSize <= MAX_BUFFER_SIZE);
    9. ...
    10. }

    2、每个assert只检验一个条件,因为同时检验多个条件时,如果断言失败,无法直观的判断是哪个条件失败

    不好:

    assert(nOffset>=0 && nOffset+nSize<=m_nInfomationSize); 

    好:

    1. assert(nOffset >= 0);
    2. assert(nOffset+nSize <= m_nInfomationSize);

    3、不能使用改变环境的语句,因为assert只在DEBUG个生效,如果这么做,会使用程序在真正运行时遇到问题

    错误: 

    assert(i++ < 100)

    这是因为如果出错,比如在执行之前i=100,那么这条语句就不会执行,那么i++这条命令就没有执行。

    正确:

    1. assert(i < 100)
    2. i++;

    4、assert和后面的语句应空一行,以形成逻辑和视觉上的一致感

    5、有的地方,assert不能代替条件过滤   

    程序一般分为Debug 版本和Release 版本,Debug 版本用于内部调试,Release 版本发行给用户使用。断言assert 是仅在Debug 版本起作用的宏,它用于检查"不应该"发生的情况。以下是一个内存复制程序,在运行过程中,如果assert 的参数为假,那么程序就会中止(一般地还会出现提示对话,说明在什么地方引发了assert)。
     

    三、举例

  • 相关阅读:
    云原生存储解决方案Rook-Ceph与Rainbond结合的实践
    开学季--CSDN联合天津科技大学校园活动正式来袭啦~
    编译安装Linux内核
    基于SSM的校园快递代取系统设计与实现
    深入理解 C 语言的内存管理
    SpringMVC-19-springmvc文件上传
    [CSS动效][按钮篇] 适用于 Material 的扁平化按钮
    VUE综合数据库编程
    cmake中的设置目标属性set_target_properties
    如何在你的 Flutter 中使用 input chip 标签组件
  • 原文地址:https://blog.csdn.net/stephenbruce/article/details/134095926