一、assert的作用
assert往往用于程序的测试版本阶段,而通常不用于release版本阶段。其于程序员而言,是起到尽早发现程序错误的作用。
assert() 的用法像是一种”契约式编程”,其表达的意思就是,若断言在我的假设条件下为真,则能够正常良好的运作,否则调用中断程序终止运行,其实就相当于一个 if 语句:
if(假设成立)
{
程序正常运行;
}
else
{
报错&&终止程序!(避免由程序运行引起更大的错误)
}
assert本身并非一个函数,而是一个宏,其原型定义在”assert.h”库中【第三部分会详细描述】。
assert 的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向 stderr 打印一条出错信息,然后通过调用 abort 来终止程序运行。
使用 assert 的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。
题外话,对于Javascript中,没有定义相应的断言,但是可以通过console.assert(‘假设条件’,’错误信息’)的方式来起到类似的测试作用;或者根据断言的定义,自己设计一个断言函数,若错误直接throw Error
二、assert的用法以及注意事项
1、重要宏定义:NDEBUG和DEBUG
- NDEBUG:控制assert是否生效, 在调试结束后#define NDEBUG 来禁用 assert 调用。例如:
#include
#define NDEBUG
#include "assert.h"
//相当于NDEBUG对assert起到如下作用
#ifdef NDEBUG
#define assert(x) ((void)0)
#else
...
- DEBUG:代表在测试阶段,可以这样定义宏以控制assert使用
#define DEBUG // release 版本注释掉即可,测试版本定义
#ifdef DEBUG
#define ASSERT(f) assert(f)
#else
#define ASSERT(f) ((void)0)
#endif
2、用法示例以及注意事项
- 在函数开始处检验传入参数的合法性
int resetBufferSize(int nNewSize) { //功能:改变缓冲区大小, //参数:nNewSize 缓冲区新长度 //返回值:缓冲区当前长度 //说明:保持原信息内容不变 nNewSize<=0表示清除缓冲区 assert(nNewSize >= 0); assert(nNewSize <= MAX_BUFFER_SIZE); ... }
- 每个assert只检验一个条件,因为同时检验多个条件时,如果断言失败,无法直观的判断是哪个条件失败
//不好:有两个条件,不知道出错是由于哪个导致 assert(nOffset>=0 && nOffset+nSize<=m_nInfomationSize); //好:一个条件,出错直观 assert(nOffset >= 0); assert(nOffset+nSize <= m_nInfomationSize);
- 不能使用改变环境的语句,因为assert只在DEBUG个生效,如果这么做,会使用程序在真正运行时遇到问题
//错误:改变了环境,使程序变量自增 assert(i++ <0 ) //正确 assert(i < 100) i++;
三、assert原理
assert在assert.h中定义的完整代码:
- 首先我们看到预处理命令 #ifdef NDEBUG 这个 NDEBUG 宏,会在程序编译为release版本时编译器会自动定义 NDEBUG这个宏, 而debug版本不会定义,所以debug时只会执行 #else 里的语句,所以根据以上代码可知,一旦程序为release版本,则assert宏只会被展开为 ((void)0) 。
基本的宏定义知识:在某个宏前面+’#’,则被替换时会在左右加上””,作为字符串。
- 假设现在非NDEBUG,此时进入执行判断表达式真假,若为假调用中断程序。对关键的定义部分化简得到第二行表达式。
//化简
(void)((!!(expression)) ||(_wassert(_CRT_WIDE(#len>0), _CRT_WIDE(__FILE__), (unsigned)(__LINE__)), 0) );
=>(void)( ( !!(expression) ) || ( _wassert( #expression,__FILE__,__LINE__ ) , 0 ) );
运行原理:
1、在debug下传入宏参数,展开为一个或表达式,而release下传入,则只会产生 ((void)0)
2、根据或表达式的判断结果,如果第一个判断结果为1,则短路,不会再执行后面的语句了;
3、如果第一个判断结果为0,则继续执行下一段语句,下一段语句调用一个函数来中断程序的执行,并打印出相应的信息。
今天的文章断言(Assert)使用、原理以及注意事项详解「建议收藏」分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/88941.html