`
caoruntao
  • 浏览: 466212 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

assert() c++ 使用方法

阅读更多

【转】http://hi.baidu.com/bevan_007/blog/item/3dc882319c3c521febc4af19.html

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))

分享到:
评论

相关推荐

    C++ 中assert()函数用法总结

    主要介绍了C++ 中assert()函数用法总结的相关资料,需要的朋友可以参考下

    深入探讨C++中的引用和ASSERT断言

    深入探讨C++中的引用和ASSERT断言,对引用和断言的理解会有很大的帮助

    c++使用json教程

    c++使用json教程,使用教程见链接https://blog.csdn.net/m0_37759974/article/details/95177771

    详解C++编程中断言static_assert的使用

    主要介绍了C++编程中断言static_assert的使用,断言在debug时非常有用,是C++入门学习中的基础知识,需要的朋友可以参考下

    Visual assert

    Visual Assert is a Visual Studio® AddIn that allows you to easily write, manage, run, and debug your C/C++ unit tests – without ever leaving the Visual Studio® IDE. No fiddling with command line ...

    业务异常提示处理 springboot+Assert(自定义断言)

    使用springboot框架快速搭建,封装自定义断言做业务校验,公共异常处理打印日志, 更简单的业务判断处理

    C++ Assert()断言机制原理以及使用方法

    下面小编就为大家带来一篇C++ Assert()断言机制原理以及使用方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    Practical C++ Programming C++编程实践

    Exceptions Adding Exceptions to the Stack Class Exceptions Versus assert Programming Exercises 23. Modular Programming Modules Public and Private The extern Storage Class Headers The Body of the ...

    深入理解C++11:C++11新特性解析与应用

    51.2.2 C++11语言变化的领域 51.3 C++11特性的分类 71.4 C++特性一览 111.4.1 稳定性与兼容性之间的抉择 111.4.2 更倾向于使用库而不是扩展语言来实现特性 121.4.3 更倾向于通用的而不是特殊的手段来实现特性 131.4....

    Visual C++ MFC 中常用宏的含义

    使用CATCH宏以获得一个异常类型,然后使用AND_CATCH宏获得随后的异常处理代码可以访问异常对象(若合适的话)已得到关于异常的特别原因的更多消息。在AND_CATCH块中调用THROW_LAST宏以便把处理过程移到下个外部异常...

    在c++中实现属性

    大多数在C++实现属性的库和编译器使用扩展技术,如Managed C++或C++ Builder,或者他们使用如通常函数的set和get方法,但那不是属性。 详述 我们首先看一下什么是属性。一个属性表现为一个字段或者成员变量,但它...

    c++头文件(传统头文件标准头文件)

    #include &lt;assert.h&gt; //设定插入点 #include &lt;ctype.h&gt; //字符处理 #include &lt;errno.h&gt; //定义错误码 #include &lt;float.h&gt; //浮点数处理 #include &lt;fstream.h&gt; //文件输入/输出 标准 C++ (同上的不再注释) ...

    Java陷阱之assert关键字

     在C和C++语言中都有assert关键,表示断言。  在Java中,同样也有assert关键字,表示断言,用法和含义都差不多。  二、语法  在Java中,assert关键字是从JAVA SE 1.4 引入的,为了避免和老版本的Java代码中...

    A JSON parser in C++

    JSON++ is a light-weight JSON parser, writer and reader written in C++. JSON++ can also convert JSON documents into lossless XML documents. Contributors http://github.com/hjiang ...

    Visual C++2010开发权威指南(共三部分).part1.rar

    5.12.2 选项卡控件的使用方法 235 5.12.3 创建选项卡控件的方法 235 5.12.4 处理选项卡控件通知消息 236 5.12.5 ctabctrl类简介 236 5.13 Visual C++ 2010 IP控件简介与开发 241 5.14 Visual C++ 2010 Picture控件...

    C++函数库大全

    C++常用函数库大全 C++常用函数库大全 #include &lt;assert.h&gt; //设定插入点 #include &lt;ctype.h&gt; //字符处理 #include &lt;errno.h&gt; //定义错误码 #include &lt;float.h&gt; //浮点数处理 #include &lt;fstream.h&gt; //文件...

Global site tag (gtag.js) - Google Analytics