【转】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() 函数用法总结 assert() 函数是在 C++ 编程语言中用于调试和检查代码的正确性的宏命令。它可以帮助开发者在开发过程中检测代码中的错误,从而提高代码的质量和可靠性。 assert() 函数的原型定义在 ...
2. **使用方法**:详细介绍不同编程语言中 `Assert` 的用法,如 C++ 中的 `assert()` 函数,Java 中的 `java.util.Assert` 类,C# 中的 `System.Diagnostics.Debug.Assert()` 和 `System.Diagnostics.Trace.Assert()...
### 深入探讨C++中的引用和ASSERT断言 #### 引用 **引用**是C++中的一项重要特性,它本质上是一个已存在的变量的别名。这意味着当我们通过引用访问一个变量时,实际上就是在直接操作那个变量。理解引用的工作原理...
本教程将介绍如何在C++项目中使用JSON,主要围绕如何解析和生成JSON数据。 首先,C++标准库并未直接支持JSON操作,因此我们需要引入第三方库来实现这一功能。这里推荐使用开源的JSON库,如nlohmann/json,这是一个...
C++编程中断言static_assert的使用是C++开发中的一个重要知识点,尤其对于初学者来说,在编写调试程序时,掌握断言的使用可以更有效地发现程序中的错误,同时static_assert作为C++11新增的特性,它允许在编译时期...
在Microsoft Visual C++ (VC) 开发环境中,`assert` 是一个非常重要的调试工具,它允许程序员在代码中设置检查点,确保程序在特定条件下的正确性。在本篇文章中,我们将深入探讨如何在VC中使用`assert`断言,以及它...
在IT行业中,异常处理是系统稳定性和健壮性的重要组成部分,尤其是在使用Spring Boot进行Web开发时。本项目“业务异常提示处理 springboot+Assert(自定义断言)”着重于利用Spring Boot的特性来构建高效、易维护的...
C++是一种广泛使用的编程语言,随着时间的推移,它经历了多次重要的标准更新,以适应现代软件开发的需求。本文将深入探讨C++98、C++03、C++11、C++14、C++17以及最新的C++20标准中的关键变化和新增特性。 **C++98/...
### 使用方法 1. **检查函数参数**:`assert()`常用于验证函数接收的参数是否符合预期。例如,在`resetBufferSize()`函数中,可以使用`assert()`来确保传入的新大小`nNewSize`是非负且不超过最大值。 ```cpp int ...
本文深入探讨了 C++ 中的static_assert关键字的作用、用法及其在编译期检查中的重要性。通过详细的代码示例,阐述了如何利用static_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++描述抽象数据类型,使用模板建立数据结构的基本方法。 八、主要代码 主要代码包括头文件datalist.h和selecttm.h,源文件error_debug.cpp。datalist.h头文件中定义了顺序表的类...
作为C++编程的必备工具,它帮助程序员掌握标准库的使用,从而提高编程效率和质量。 在《The C++ Standard Library》之外,还有一本由Björn Karlsson所著的《Beyond the C++ Standard Library: An Introduction to ...
C++是一种广泛使用的面向对象的编程语言,其标准历经多个版本的发展,逐步增加了新的特性,提高了效率和灵活性。本文将详细介绍C++03、C++11、C++14和C++17这四个主要版本的关键知识点。 C++03是C++的早期标准,它...
5. **静态断言(Static_assert)**:静态断言可以在编译时检查条件,如果条件不满足,编译器会报错,有助于早期发现错误。 6. **初始化列表(Initializer Lists)**:初始化列表允许在构造函数中使用花括号进行初始...
8. **编译器.doc**:可能涵盖了不同的C++编译器,比如GCC、Clang、MSVC等,它们的特点、使用方法和编译选项,以及跨平台编译的策略。 9. **zijiexu_pic_1.jpg、zijiexu_pic_2.jpg**:这些图片可能包含示例代码、...
C++短信接口开发是指使用C++语言开发短信接口,可以发送验证码短信、订单通知短信等。以下是C++短信接口开发的详细信息: 1. 接口类型:互亿无线触发短信接口,该接口支持发送验证码短信、订单通知短信等。 2. ...
- Microsoft Visual C++ 2010(VC++ 11.0):对C++11标准进行了大量支持,包括右值引用、静态_assert和多线程库等,提高了代码的并发性和效率。 4. **32位与64位的区别**: 32位版本适用于运行在32位操作系统上的...
可以使用GDB这样的调试工具,以及`assert`语句来验证程序内部逻辑。 综上所述,这个"贪吃蛇C++源码"项目涵盖了C++语言的多个核心概念,包括面向对象编程、数据结构、算法应用、输入/输出处理以及错误处理等。通过...