防御式编程之断言assert的使用

防御式编程的重点就是需要防御一些程序未曾预料的错误,这是一种提高软件质量的辅助性方法,断言assert就用于防御式编程,编写代码时,我们总是会做出一些假设,断言就是用于在代码中捕捉这些假设。 使用断言是为了验证预期的结果——当程序执行到断言的位置时,对应的断言应该为真; 若断言不为真时,程序会终止执行,并给出错误信息。 可以在任何时候启用和禁用断言验证,因此可以在程序调试时启用断言而在程序发布时禁用断言。 同样,程序投入运行后,最终用户在遇到问题时可以重新启用断言。
1、原型函数
在大部分编译器下,assert() 是一个宏; 在少数的编译器下,assert() 就是一个函数。 我们不需要关心这些差异,可以只把 assert()当作函数使用即可。 即:
void assert(int expression)在程序运行时它会计算括号内的表达式,如果 expression为非0说明其值为真,assert()不执行任何动作,程序继续执行后面的语句; 如果 expression为0说明其值为假,assert()将会报告错误,并终止程序的执行,值得了解的是,程序终止是调用abort()函数,这个函数功能就是终止程序执行,直接从调用的地方跳出,abort()函数也是标准库函数,在
2、详细释义
assert() 在c标准库中的
#ifdef ndebug#define assert(e) ((void)0)#else#define assert(e) ((void) ((e) ? ((void)0) : __assert (#e, __file__, __line__)))#endif可以看到在定义了ndebug时,assert()无效,只有在未定义ndebug时,assert()才实现具体的函数功能。 ndebug是“no debug”的意思,也即“非调试”。 程序一般分为debug版本和release版本,debug版本是程序员在测试代码期间使用的编译版本,release版本是将程序提供给用户时使用的发布版本,一般来说断言assert()是仅在debug版本起作用的宏。 在发布版本时,我们不应该再依赖assert()宏,因为程序一旦出错,assert()会抛出一段用户看不懂的提示信息,并毫无预警地终止程序执行,这样会严重影响软件的用户体验,所以在发布模式下应该让assert()失效,另外在程序中频繁的调用assert()会影响程序的性能,增加额外的开销。 因此可以在
#define ndebug //定义ndebug #ifdef ndebug#define assert(e) ((void)0)#else#define assert(e) ((void) ((e) ? ((void)0) : __assert (#e, __file__, __line__)))#endif定义ndbug时:当定义了ndebug之后,assert()执行的具体函数就变成了 ((void)0),这表示啥也不干了,宏里面这样用的目的是防止该宏被用作右值,因为void类型不能用作右值。 所以当在头文件中定义了ndebug之后,assert()的检测功能就自动失效了。
未定义ndbug时:可以看到assert()执行实际上是通过三目运算符来判断表达式e的真假,执行相应的处理。 当表达式e为真时,执行(void)0,即什么也不执行,程序继续运行; 当表达式e为假时,那么它会打印出来assert的内容、当前的文件名、当前行号,接着终止程序执行。
3、用法举例
在未定义ndbug时,assert()功能生效的情况下,来看一个简单的assert()使用的例子:
#include #include void main(){ int i = 8; assert(i > 0); printf(i = %d\\n, i); i = -8; assert(i > 0); printf(i = %d\\n, i);}可以看出在程序中使用assert(i > 0)来判断; 当 i > 0 时,assert的判断表达式为真,assert不生效; 当 i 0) ... else if(a 0); ...}void fun2(int *p){ assert(p != null); ...}不要使用影响正常逻辑的判断条件语句assert的判断条件语句一定是确定的,在debug版本中使用的排除掉错误的条件逻辑,不要影响到release版本时的正常逻辑。 例如下面的例子,在debug版本时,i++到>=100时,assert生效,程序终止; 但是到了release版本,由于要增加ndebug宏,assert()无效。 assert(i++ < 100)就变成了空操作(void)0;由于没有i++语句执行,那么while成了死循环。
#include #include void main(){ int i = 0; while(i <= 110) { assert(i++ 0 && b > 5); ...}void fun2(int a, int b) //正确使用{ assert(a > 0); assert(b > 5); ...}

Lora数据包的关键参数分析
智慧城市中有哪一些网络上的安全问题可能出现
73M1866B/73M1966B PCM连接
基于MPQ8645P的高密度电源芯片解决方案
一种凸型多模光波导及多模色散调控方法
防御式编程之断言assert的使用
基于优化的多传感器全局位姿估计框架
松下电器制造行业系统解决方案为业务现场流程带来革新
Fastrax发布最新全球卫星导航定位模块IT600
基于FPGA的可调FIR滤波器在实际通信系统中的实现方法设计
基于LTV350QV-F05 TFT LCD屏实现GPS导航仪的设计
C语言中if语句、if-else语句和switch语句详解
爱啃萝卜机器人公司研发出搬运机器人可轻松完成物流转运与投递任务
指纹识别:华为P10向前、三星S8向后
GGII:2022年中国锂电叠片设备市场规模同比增长68%
TFT LCD零组件、材料市场迎来戏剧性变化
深度神经网络竟然是模块化的?
企业采用区块链和信任证明可以大大降低数据被泄露的几率
深度解析深度学习的知识蒸馏技术
工业4.0为医疗装置产业带来八大益处