C语言断言的应用
2016-07-21 21:35
411 查看
一、断言概况
1、断言
(1)在使用C语言编写工程代码时,我们总会对某种假设条件进行检查,断言就是用于在代码中捕捉这些假设,可以将断言看作是异常处理的一种高级形式。
(2)断言表示为一些布尔表达式,程序员相信在程序中的某个特定点该表达式值为真。可以在任何时候启用和禁用断言验证,因此可以在测试时启用断言,而在部署时禁用断言。
(3)同样,程序投入运行后,最终用户在遇到问题时可以重新起用断言。它可以快速发现并定位软件问题,同时对系统错误进行自动报警。断言可以对在系统中隐藏很深,用其它手段极难发现的问题可以用断言来进行定位,从而缩短软件问题定位时间,提高系统的可测性。实际应用时,可根据具体情况灵活地设计断言。
2、一般使用的地方
(1)在函数的入口处,使用断言检查参数的有效性(合法性)。
(2)在编写函数时,要进行反复的考查,并且自问:“我打算做哪些假定?”一旦确定了的假定,就要使用断言对假定进行检查。
(3)可以在预计正常情况下程序不会到达的地方放置断言。(如assert (0);)
(4)使用断言测试方法执行的前置条件和后置条件 。
(5)使用断言检查类的不变状态,确保任何情况下,某个变量的状态必须满足。(如某个变量的变化范围)
二、断言的使用方式
1、使用库函数中的断言
(1)assert宏的原型定义在<assert.h>中,其作用是先计算表达式expression,如果expression的值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用库函数abort()来终止程序运行。
(2)例子
#include <stdio.h>
#include <assert.h>
typedef unsigned char uint8_t;
typedef unsigned long uint32_t;
int main( void )
{
uint8_t var;
var = 0;
assert( var );
return 0;
}
如图所示,运行到assert的时候,因为表达式中的结果为0,所以执行assert内部的语句,打印出错表达式,并且定位出错的文件位置以及出错行数,最后调用abort()函数,终止程序。
如果我把assert( var )改成assert( var == 1 ),则打印出来的是“Assertion failed: var==1, file E:\……”
(3)禁止断言的方法
在#include<assert.h>的前面加上#define NDEBUG
注意:一定是要在该头文件之前添加#define NDEBUG,在头文件之后添加是不能禁止断言的
2、自定义断言函数
(1)根据库函数assert()所展示的功能,我们也可以自定义一个带参宏,并且灵活处理断言的方式
(2)例子
(3)禁止断言的方法
我们可以使用条件编译来选择是否使用断言。
如果使用断言,就使用#define USE_FULL_ASSERT,那么就会用assert_failed代替assert_param(expr),并且声明assert_failed,然后在该函数中实现断言的功能;否则,用(void)0代替assert_param(expr),表示为空语句。
三、断言与if
1、两者区别
(1)if是在最终发布的版本中真实存在的,用于处理程序运行过程中产生的错误(例如处理用户错误输入),以提高程序的健壮性。
(2)断言用于开发阶段的调试,捕捉不应该发生的非法情况,并迅速定位问题。发布的时候需要把断言去掉。
2、例子
(1)注意到我对source是否为NULL是用assert检查的,但对result是不是为NULL是用if语句判断的
(2)这是因为在调用代码正确的情况下source必然不为NULL,如果断言失败,说明调用代码中有错误,需要修改;但result作为malloc的返回值则不一定,在malloc代码无误的情况下仍然可能返回NULL——当内存块不足时。
(3)最后又用assert对strcpy的结果进行检查,因为只要代码正确,无论什么情况strcpy应该正常完成复制,它没有malloc那种异常情况存在。
参考网址:
【1】C语言之断言http://blog.csdn.net/wxq1987525/article/details/6639220
【2】用断言好还是用if好http://bbs.csdn.net/topics/390680318
【3】关于C语言的assert(断言)http://blog.csdn.net/engrossment/article/details/8118234
1、断言
(1)在使用C语言编写工程代码时,我们总会对某种假设条件进行检查,断言就是用于在代码中捕捉这些假设,可以将断言看作是异常处理的一种高级形式。
(2)断言表示为一些布尔表达式,程序员相信在程序中的某个特定点该表达式值为真。可以在任何时候启用和禁用断言验证,因此可以在测试时启用断言,而在部署时禁用断言。
(3)同样,程序投入运行后,最终用户在遇到问题时可以重新起用断言。它可以快速发现并定位软件问题,同时对系统错误进行自动报警。断言可以对在系统中隐藏很深,用其它手段极难发现的问题可以用断言来进行定位,从而缩短软件问题定位时间,提高系统的可测性。实际应用时,可根据具体情况灵活地设计断言。
2、一般使用的地方
(1)在函数的入口处,使用断言检查参数的有效性(合法性)。
(2)在编写函数时,要进行反复的考查,并且自问:“我打算做哪些假定?”一旦确定了的假定,就要使用断言对假定进行检查。
(3)可以在预计正常情况下程序不会到达的地方放置断言。(如assert (0);)
(4)使用断言测试方法执行的前置条件和后置条件 。
(5)使用断言检查类的不变状态,确保任何情况下,某个变量的状态必须满足。(如某个变量的变化范围)
二、断言的使用方式
1、使用库函数中的断言
(1)assert宏的原型定义在<assert.h>中,其作用是先计算表达式expression,如果expression的值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用库函数abort()来终止程序运行。
(2)例子
#include <stdio.h>
#include <assert.h>
typedef unsigned char uint8_t;
typedef unsigned long uint32_t;
int main( void )
{
uint8_t var;
var = 0;
assert( var );
return 0;
}
如图所示,运行到assert的时候,因为表达式中的结果为0,所以执行assert内部的语句,打印出错表达式,并且定位出错的文件位置以及出错行数,最后调用abort()函数,终止程序。
如果我把assert( var )改成assert( var == 1 ),则打印出来的是“Assertion failed: var==1, file E:\……”
(3)禁止断言的方法
在#include<assert.h>的前面加上#define NDEBUG
注意:一定是要在该头文件之前添加#define NDEBUG,在头文件之后添加是不能禁止断言的
2、自定义断言函数
(1)根据库函数assert()所展示的功能,我们也可以自定义一个带参宏,并且灵活处理断言的方式
(2)例子
#include <stdio.h> typedef unsigned char uint8_t; typedef unsigned long uint32_t; #define USE_FULL_ASSERT #ifdef USE_FULL_ASSERT #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__, __func__)) void assert_failed(uint8_t* file, uint32_t line); #else #define assert_param(expr) ((void)0) #endif void assert_failed(uint8_t* file, uint32_t line, uint8_t* func) { printf("There is an error in line%d, file name:%s, function name:%s", line, file, func); abort(); } int main( void ) { int var = 0; assert_param( var ); return 0; }
(3)禁止断言的方法
我们可以使用条件编译来选择是否使用断言。
如果使用断言,就使用#define USE_FULL_ASSERT,那么就会用assert_failed代替assert_param(expr),并且声明assert_failed,然后在该函数中实现断言的功能;否则,用(void)0代替assert_param(expr),表示为空语句。
三、断言与if
1、两者区别
(1)if是在最终发布的版本中真实存在的,用于处理程序运行过程中产生的错误(例如处理用户错误输入),以提高程序的健壮性。
(2)断言用于开发阶段的调试,捕捉不应该发生的非法情况,并迅速定位问题。发布的时候需要把断言去掉。
2、例子
char *clone_string( const char *source ) { char *result; assert( source != NULL ); result = ( char* )malloc( strlen(source) + 1 ); if( result != NULL ) { strcpy( result, source ); assert( strcmp(result, source) == 0 ); } return result; }
(1)注意到我对source是否为NULL是用assert检查的,但对result是不是为NULL是用if语句判断的
(2)这是因为在调用代码正确的情况下source必然不为NULL,如果断言失败,说明调用代码中有错误,需要修改;但result作为malloc的返回值则不一定,在malloc代码无误的情况下仍然可能返回NULL——当内存块不足时。
(3)最后又用assert对strcpy的结果进行检查,因为只要代码正确,无论什么情况strcpy应该正常完成复制,它没有malloc那种异常情况存在。
参考网址:
【1】C语言之断言http://blog.csdn.net/wxq1987525/article/details/6639220
【2】用断言好还是用if好http://bbs.csdn.net/topics/390680318
【3】关于C语言的assert(断言)http://blog.csdn.net/engrossment/article/details/8118234
相关文章推荐
- [转]快速幂(C语言实现) 超详细
- La 4080 Warfare and logistics Dijkstra
- C++析构函数为什么要为虚函数
- C++模板定义和实现分离导致的编译错误
- 关于windows下c/c++的rand()的一个测试
- c语言实现字符串的分割
- c++ learning note
- 嵌入式系统上C++调用C语言接口代码链接时找不到C函数问题处理
- 1003. 我要通过!(20)
- C/C++笔记--程序内存分区分析
- Leetcode 190. Reverse Bits (Easy) (cpp)
- 2016ACM多校训练第一场_1001_Abandoned Country 并查集+DFS
- PAT乙级1002. 写出这个数 C++
- C语言位操作
- C++STL之所有算法介绍
- C语言内存话题
- C语言程序设计练习2(窗口服务指示系统3.5 )
- C++ hdoj 2013
- 浅谈C语言中结构体的初始化
- Remove Duplicates from Sorted Array II