c++ assert() 使用方法
assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,原型定义:
#include <assert.h>
void assert( int expression );
assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,
然后通过调用 abort 来终止程序运行。
请看下面的程序清单badptr.c:
#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;
}
[root@localhost error_process]# gcc badptr.c
[root@localhost error_process]# ./a.out
a.out: badptr.c:14: main: Assertion `fp'' failed.
已放弃
使用assert的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。
在调试结束后,可以通过在包含#include <assert.h>的语句之前插入 #define NDEBUG 来禁用assert调用,示例代码如下:
#include <stdio.h>
#define NDEBUG
#include <assert.h>
用法总结与注意事项:
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不能代替条件过滤
文章出处:http://www.diybl.com/course/3_program/c++/cppjs/20071111/85534.html
摘自《高质量C/C++编程指南》Page 41-42...
程序一般分为Debug 版本和Release 版本,Debug 版本用于内部调试,Release 版本发行给用户使用。
断言assert 是仅在Debug 版本起作用的宏,它用于检查“不应该”发生的情况。示例6-5 是一个内存复制函数。在运行过程中,如果assert 的参数为假,那么程序就会中止(一般地还会出现提示对话,说明在什么地方引发了assert)。
void *memcpy(void *pvTo, const void *pvFrom, size_t size)
{
assert((pvTo != NULL) && (pvFrom != NULL)); // 使用断言
byte *pbTo = (byte *) pvTo; // 防止改变pvTo 的地址
byte *pbFrom = (byte *) pvFrom; // 防止改变pvFrom 的地址
while(size -- > 0)
*pbTo ++ = *pbFrom ++ ;
return pvTo;
}
示例6-5 复制不重叠的内存块
assert 不是一个仓促拼凑起来的宏。为了不在程序的Debug 版本和Release 版本引起差别,assert 不应该产生任何副作用。所以assert 不是函数,而是宏。程序员可以把assert看成一个在任何系统状态下都可以安全使用的无害测试手段。如果程序在 assert 处终止了,并不是说含有该assert 的函数有错误,而是调用者出了差错,assert 可以帮助我们找到发生错误的原因。
很少有比跟踪到程序的断言,却不知道该断言的作用更让人沮丧的事了。你化了很多时间,不是为了排除错误,而只是为了弄清楚这个错误到底是什么。有的时候,程序员偶尔还会设计出有错误的断言。所以如果搞不清楚断言检查的是什么,就很难判断错误是出现在程序中,还是出现在断言中。幸运的是这个问题很好解决,只要加上清晰的注释即可。这本是显而易见的事情,可是很少有程序员这样做。这好比一个人在森林里,看到树上钉着一块“危险”的大牌子。但危险到底是什么?树要倒?有废井?有野兽?除非告诉人们“危险”是什么,否则这个警告牌难以起到积极有效的作用。难以理解的断言常常被程序员忽略,甚至被删除。
【规则6-5-1】使用断言捕捉不应该发生的非法情况。不要混淆非法情况与错误情况之间的区别,后者是必然存在的并且是一定要作出处理的。
【规则6-5-2】在函数的入口处,使用断言检查参数的有效性(合法性)。
【建议6-5-1】在编写函数时,要进行反复的考查,并且自问:“我打算做哪些假定?”一旦确定了的假定,就要使用断言对假定进行检查。
【建议6-5-2】一般教科书都鼓励程序员们进行防错设计,但要记住这种编程风格可能会隐瞒错误。当进行防错设计时,如果“不可能发生”的事情的确发生了,则要使用断言进行报警。
ASSERT宏中应该包含的元素:
判断条件;输出当前断言失败的位置(文件、行数等);返回错误;终止程序...
几种典型的ASSERT的写法:
VC中的写法:
#define ASSERT(f) \
do \
{ \
if (!(f) && AfxAssertFailedLine(THIS_FILE, __LINE__)) \
AfxDebugBreak(); \
} while (0) \
#define _ASSERT(expr) \
do { if (!(expr) && \
(1 == _CrtDbgReport(_CRT_ASSERT, __FILE__, __LINE__, NULL, NULL))) \
_CrtDbgBreak(); } while (0)
其他平台的写法:
# define ASSERT(x) ((x) || (dbg_printf("assertion failed ("__FILE__":%d): \"%s\"\n",__LINE__,#x), break_point(), FALSE))
原网站地址:http://hi.baidu.com/uwbadnhctpkopwr/item/1d5d1e1d316c79fcdceeca0a
c++ assert() 使用方法的更多相关文章
- Assert.IsNotNull 方法(判断对象不为NULL)
Assert.IsNotNull 方法 Visual Studio 2012 其他版本 Visual Studio 2010 Visual Studio 2008 Visual Studio 20 ...
- Junit中Assert.assertEquals()和Assert.assertSame方法有什么异同
1)提供的接口数量不完全相同.assertEquals支持boolean,long,int等等java primitiveType变量.assertSame只支持Object. 2)比较的逻辑不同,结 ...
- java——assert(断言)方法
包:org.junit.Assert; assertEqual(a,b,[msg='测试失败时打印的信息']): 断言a和b是否相等,相等则测试用例通过. assertNotEqual(a,b,[ms ...
- node.js自动化测试断言包assert的方法说明
参考以下文档 http://yijiebuyi.com/blog/ca2c0edf447624bd4d527490c9fce369.html http://www.cnblogs.com/softlo ...
- python_way,day8 面向对象【多态、成员--字段 方法 属性、成员修饰符、特殊成员、异常处理、设计模式之单例模式、模块:isinstance、issubclass】
python_way day8 一.面向对象三大特性: 多态 二.面向对象中的成员 字段.方法属性 三.成员修饰符 四.特殊成员 __init__.__doc__.__call__.__setitem ...
- 单元测试中Assert类
一.Assert类的使用 1.Assert类所在的命名空间为Microsoft.VisualStudio.TestTools.UnitTesting 在工程文件中只要引用Microsoft.Visua ...
- 使用xUnit为.net core程序进行单元测试 -- Assert
第一部分: http://www.cnblogs.com/cgzl/p/8283610.html Assert Assert做什么?Assert基于代码的返回值.对象的最终状态.事件是否发生等情况来评 ...
- pytest自动化7:assert断言
前言:assert断言就是将实际结果和期望结果做对比,符合预期结果就测试pass,不符合预期就测试failed. 实例1:简单断言 实例1优化版--增加异常信息文字描述 异常断言 excinfo 是一 ...
- pytest七:assert
断言是写自动化测试基本最重要的一步,一个用例没有断言,就失去了自动化测试的意义了.什么是断言呢?简单来讲就是实际结果和期望结果去对比,符合预期那就测试 pass,不符合预期那就测试 failed py ...
随机推荐
- ASP.NET MVC ViewBag/ViewData/TempData区别
ViewBag/ViewData public dynamic ViewBag { get; } public ViewDataDictionary ViewData { get; set; } Vi ...
- 基于CentOS体验万象优图鉴黄服务
系统要求:CentOS 7.2 64 位操作系统 初始化配置 使用万象优图图片鉴黄 API 接口,我们需要先完成以下步骤: 获取腾讯云账号 APP ID 配置云 API 公钥/密钥 配置优图 buck ...
- OpenCV 学习笔记 06 图像检索以及基于图像描述符的搜索
OpenCV 可以检测图像的主要特征,然后提取这些特征,使其成为图像描述符,这些图像特征可作为图像搜索的数据库:此外可以利用关键点将图像拼接 stitch 起来,组成一个更大的图像.如将各照片组成一个 ...
- ARM与X86 CPU架构对比区别
CISC(复杂指令集计算机)和RISC(精简指令集计算机)是当前CPU的两种架构.它们的区别在于不同的CPU设计理念和方法.早期的CPU全部是CISC架构,它的设计目的是 CISC要用最少的机器语言 ...
- stale element reference: element is not attached to the page document 异常
在执行脚本时,有时候引用一些元素对象会抛出如下异常 org.openqa.selenium.StaleElementReferenceException: stale element referenc ...
- [svc]find+xargs/sed&sed后向引用+awk多匹配符+过滤行绝招总结&&产生随机数
30天内的文件打包 find ./test_log -type f -mtime -30|xargs tar -cvf test_log.tar.gz find,文件+超过7天+超过1M的+按日期为文 ...
- Unity实现混合模式的ADD模式
一般来说,2D的特效都会用到ADD模式来播放,但是Unity居然没有内置任何的混合模式,网上资料太少,没有写好的Shader,这里提供下我自己编写Shader: Shader "Unlit/ ...
- linux每日命令(36):wc命令
Linux系统中的wc(Word Count)命令的功能为统计指定文件中的字节数.字数.行数,并将统计结果显示输出. 一.命令格式 wc [-clw][--help][--version][文件... ...
- linux每日命令(38):iostat命令
Linux系统中的 iostat是I/O statistics(输入/输出统计)的缩写,iostat工具将对系统的磁盘操作活动进行监视.它的特点是汇报磁盘活动统计情况,同时也会汇报出CPU使用情况.同 ...
- pivot 与 unpivot函数
pivot 与 unpivot函数 pivot 与 unpivot 函数是SQL05新提供的2个函数 灰常灰常的实用 ----------------------------------------- ...