`
caoruntao
  • 浏览: 480947 次
  • 性别: 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() 函数用法总结 assert() 函数是在 C++ 编程语言中用于调试和检查代码的正确性的宏命令。它可以帮助开发者在开发过程中检测代码中的错误,从而提高代码的质量和可靠性。 assert() 函数的原型定义在 ...

    Assert使用

    2. **使用方法**:详细介绍不同编程语言中 `Assert` 的用法,如 C++ 中的 `assert()` 函数,Java 中的 `java.util.Assert` 类,C# 中的 `System.Diagnostics.Debug.Assert()` 和 `System.Diagnostics.Trace.Assert()...

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

    ### 深入探讨C++中的引用和ASSERT断言 #### 引用 **引用**是C++中的一项重要特性,它本质上是一个已存在的变量的别名。这意味着当我们通过引用访问一个变量时,实际上就是在直接操作那个变量。理解引用的工作原理...

    c++使用json教程

    本教程将介绍如何在C++项目中使用JSON,主要围绕如何解析和生成JSON数据。 首先,C++标准库并未直接支持JSON操作,因此我们需要引入第三方库来实现这一功能。这里推荐使用开源的JSON库,如nlohmann/json,这是一个...

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

    C++编程中断言static_assert的使用是C++开发中的一个重要知识点,尤其对于初学者来说,在编写调试程序时,掌握断言的使用可以更有效地发现程序中的错误,同时static_assert作为C++11新增的特性,它允许在编译时期...

    VC中如何使用ASSERT断言

    在Microsoft Visual C++ (VC) 开发环境中,`assert` 是一个非常重要的调试工具,它允许程序员在代码中设置检查点,确保程序在特定条件下的正确性。在本篇文章中,我们将深入探讨如何在VC中使用`assert`断言,以及它...

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

    在IT行业中,异常处理是系统稳定性和健壮性的重要组成部分,尤其是在使用Spring Boot进行Web开发时。本项目“业务异常提示处理 springboot+Assert(自定义断言)”着重于利用Spring Boot的特性来构建高效、易维护的...

    C++98/C++03/C++11/C++14/C++17/C++20 标准帮助文档 2020-09-04

    C++是一种广泛使用的编程语言,随着时间的推移,它经历了多次重要的标准更新,以适应现代软件开发的需求。本文将深入探讨C++98、C++03、C++11、C++14、C++17以及最新的C++20标准中的关键变化和新增特性。 **C++98/...

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

    ### 使用方法 1. **检查函数参数**:`assert()`常用于验证函数接收的参数是否符合预期。例如,在`resetBufferSize()`函数中,可以使用`assert()`来确保传入的新大小`nNewSize`是非负且不超过最大值。 ```cpp int ...

    C++ 中 static-assert:编译期的强力断言机制解析

    本文深入探讨了 C++ 中的static_assert关键字的作用、用法及其在编译期检查中的重要性。通过详细的代码示例,阐述了如何利用static_assert对代码中的各种条件进行静态验证,包括类型特征、常量表达式、模板参数约束...

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

    数据结构C++基础编程

    通过这些实验,我们可以掌握使用C++描述抽象数据类型,使用模板建立数据结构的基本方法。 八、主要代码 主要代码包括头文件datalist.h和selecttm.h,源文件error_debug.cpp。datalist.h头文件中定义了顺序表的类...

    The_C++_Standard_Library(c++中文版).pdf 编程必备

    作为C++编程的必备工具,它帮助程序员掌握标准库的使用,从而提高编程效率和质量。 在《The C++ Standard Library》之外,还有一本由Björn Karlsson所著的《Beyond the C++ Standard Library: An Introduction to ...

    C++标准文档

    C++是一种广泛使用的面向对象的编程语言,其标准历经多个版本的发展,逐步增加了新的特性,提高了效率和灵活性。本文将详细介绍C++03、C++11、C++14和C++17这四个主要版本的关键知识点。 C++03是C++的早期标准,它...

    C++程序设计语言

    5. **静态断言(Static_assert)**:静态断言可以在编译时检查条件,如果条件不满足,编译器会报错,有助于早期发现错误。 6. **初始化列表(Initializer Lists)**:初始化列表允许在构造函数中使用花括号进行初始...

    C++高级应用完整版

    8. **编译器.doc**:可能涵盖了不同的C++编译器,比如GCC、Clang、MSVC等,它们的特点、使用方法和编译选项,以及跨平台编译的策略。 9. **zijiexu_pic_1.jpg、zijiexu_pic_2.jpg**:这些图片可能包含示例代码、...

    c++短信接口开发_c++发送短信验证码通知_c++短信demo示例.docx

    C++短信接口开发是指使用C++语言开发短信接口,可以发送验证码短信、订单通知短信等。以下是C++短信接口开发的详细信息: 1. 接口类型:互亿无线触发短信接口,该接口支持发送验证码短信、订单通知短信等。 2. ...

    microsoft visual c++ redistributable

    - Microsoft Visual C++ 2010(VC++ 11.0):对C++11标准进行了大量支持,包括右值引用、静态_assert和多线程库等,提高了代码的并发性和效率。 4. **32位与64位的区别**: 32位版本适用于运行在32位操作系统上的...

    贪吃蛇C++源码

    可以使用GDB这样的调试工具,以及`assert`语句来验证程序内部逻辑。 综上所述,这个"贪吃蛇C++源码"项目涵盖了C++语言的多个核心概念,包括面向对象编程、数据结构、算法应用、输入/输出处理以及错误处理等。通过...

Global site tag (gtag.js) - Google Analytics