assert宏的原型定义在assert.h中,其作用是如果它的条件返回错误,则终止程序执行.
原型定义:
#include "assert.h"
void assert( int expression );
assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。
请看下面的程序清单badptr.c:
#include
#include
#include
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;
}
使用assert的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。
在调试结束后,可以通过在包含#include 的语句之前插入 #define NDEBUG 来禁用assert调用,示例代码如下:
#include
#define NDEBUG
#include
用法总结与注意事项:
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不能代替条件过滤
#C++
程序一般分为Debug 版本和Release 版本,Debug 版本用于内部调试,Release 版本发行给用户使用。断言assert 是仅在Debug 版本起作用的宏,它用于检查“不应该”发生的情况。以下是一个内存复制程序,在运行过程中,如果assert 的参数为假,那么程序就会中止(一般地还会出现提示对话,说明在什么地方引发了assert)。
//复制不重叠的内存块
void memcpy(void *pvTo, void *pvFrom, size_t size)
{
void *pbTo = (byte *) pvTo;
void *pbFrom = (byte *) pvFrom;
assert( pvTo != NULL && pvFrom != NULL );
while(size - - > 0 )
*pbTo + + = *pbFrom + + ;
return (pvTo);
}
assert 不是一个仓促拼凑起来的宏,为了不在程序的Debug 版本和Release 版本引起差别,assert 不应该产生任何副作用。所以assert 不是函数,而是宏。程序员可以把assert 看成一个在任何系统状态下都可以安全使用的无害测试手段。
很少有比跟踪到程序的断言,却不知道该断言的作用更让人沮丧的事了。你化了很多时间,不是为了排除错误,而只是为了弄清楚这个错误到底是什么。有的时候,程序员偶尔还会设计出有错误的断言。所以如果搞不清楚断言检查的是什么,就很难判断错误是出现在程序中,还是出现在断言中。幸运的是这个问题很好解决,只要加上清晰的注释即可。这本是显而易见的事情,可是很少有程序员这样做。这好比一个人在森林里,看到树上钉着一块“危险”的大牌子。但危险到底是什么?树要倒?有废井?有野兽?除非告诉人们“危险”是什么,否则这个警告牌难以起到积极有效的作用。难以理解的断言常常被程序员忽略,甚至被删除。 [Maguire 1993]
以下是使用断言的几个原则:
(1)使用断言捕捉不应该发生的非法情况。不要混淆非法情况与错误情况之间的区别,后者是必然存在的并且是一定要作出处理的。
(2)使用断言对函数的参数进行确认。
(3)在编写函数时,要进行反复的考查,并且自问:“我打算做哪些假定?”一旦确定了的
假定,就要使用断言对假定进行检查。
(4)一般教科书都鼓励程序员们进行防错性的程序设计,但要记住这种编程风格会隐瞒错误。当进行防错性编程时,如果“不可能发生”的事情的确发生了,则要使用断言进行报警。
ASSERT ()是一个调试程序时经常使用的宏,在程序运行时它计算括号内的表达式,如果表达式为FALSE (0), 程序将报告错误,并终止执行。如果表达式不为0,则继续执行后面的语句。这个宏通常原来判断程序中是否出现了明显非法的数据,如果出现了终止程序以免导致严重后果,同时也便于查找错误。
ASSERT只有在Debug版本中才有效,如果编译为Release版本则被忽略。
---------------------------------------------------------------
ASSERT宏定义如下
#define ASSERT(f)
do
{
if (!(f) && AfxAssertFailedLine(THIS_FILE, __LINE__))
AfxDebugBreak();
} while (0)
ASSERT(逻辑表达式)
如果括号中的逻辑表达式值为假的话,会弹出调试命令窗口,提示具体在哪个文件的哪一行发生了断言错误!
---------------------------------------------------------------
ASSERT
Evaluates an expression, and displays a diagnostic message if the expression is FALSE. Ignored in retail builds.
Syntax
ASSERT(
cond
);
Parameters
cond
Expression to evaluate.
Remarks
In debug builds, if the expression is FALSE, this macro displays a message box with the text of the expression, the name of the source file, and the line number. The user can ignore the assertion, enter the debugger, or quit the application.
Example
ASSERT(rtStartTime <= rtEndTime);
---------------------------------------------------------------
断言(ASSERT)的使用,方法很简单。为什么要用,初学者可能比较迷惑。
契约式编程讲的比较清楚,建议可以先看看这类书。
一个函数由前置条件、后置条件和不变式组成。在VC中,我们可以通过断言来保证这三个条件。可以大大提高了软件的质量。
---------------------------------------------------------------
如果ASSERT()中的条件不成立(比如 ASSERT(0) ; ),会弹出一个比较吓人的对话框。
点击重试,可以到达 ASSERT 断言不成立的那一行,
此时可以在watch窗口查看变量值,找出出错的原因。
如果程序能够继续运行,可以按F5继续调试。
分享到:
相关推荐
### 关于assert_param的理解与应用 #### 一、assert_param简介 `assert_param`是一个用于检查函数参数有效性的宏,在调试阶段特别有用。它只在`DEBUG`模式下生效,这意味着在发布版本(非调试版本)中,这些检查将...
3. **规则3**:尽管ASSERT宏有助于调试,但使用时需谨慎,避免依赖其在Release模式下的行为。可以考虑将重要的ASSERT转换为VERIFY宏,或直接移除不必要依赖DEBUG宏的代码。 为了使Debug模式更接近Release模式以重现...
在Android应用开发中,数据库是存储和管理应用程序数据的关键组件。有时,我们可能需要在应用程序启动时预先填充一些数据,这时可以将预置的数据库文件放入`assets`目录下,然后在程序运行时读取并加载。...
这个名为"json-path-assert-2.1.0.zip"的压缩包可能是与JSON Path的一个特定版本,2.1.0,以及相关的断言库有关,用于验证JSON数据。JSON Path是一个查询JSON对象的表达式语言,类似于XPath对于XML。另一方面,"json...
在Node.js中,`assert`模块提供了丰富的断言方法来帮助开发者确保程序的正确性。以下是对`assert`模块中各个方法的详细说明: 1. `assert(value[, message])`: 这是最基础的断言方法,它检查给定的`value`是否为真...
文章建议,除非Java在未来版本中默认开启断言检查,否则开发者应避免使用assert关键字,转而使用JUnit等更为强大的测试工具。同时,文章建议开发者在决定是否使用断言时,应该仔细权衡其带来的好处与可能引发的麻烦...
总结来说,函数重载是C++的一个核心特性,允许根据不同的参数列表调用同名函数,而`assert`和`static_assert`则提供了强大的错误检测机制,帮助开发者确保代码的正确性和健壮性。正确理解和使用这些概念是成为高效...
`assert`语句是Python提供的一个内置工具,用于进行条件检查,帮助开发者在开发阶段捕获潜在的逻辑错误。本文将深入讲解`assert`的用法及其在错误处理中的作用。 `assert`语句的基本结构是: ```python assert ...
C标准库中的`<assert.h>`头文件提供了一个名为`assert`的宏,用于在程序开发阶段进行调试。这个宏允许程序员在代码的关键位置插入断言,以确保特定条件始终为真。如果断言失败,即条件为假,`assert`会输出一条错误...
2. **丰富的断言方法**:除了基本的`assert.ok()`之外,`assert.js`还提供了多种断言方法,如`assert.equal()`, `assert.notEqual()`, `assert.deepEqual()`, `assert.ifError()`等,覆盖了各种比较需求。...
`assert` 的基本调用格式是 `assert(logicExpression)`,其中 `logicExpression` 是一个布尔表达式。如果这个表达式的值为 `false`,即表达式的逻辑结果不成立,那么 `assert` 会终止程序的执行,并打印出错误信息,...
C++编程中断言static_assert的使用是C++开发中的一个重要知识点,尤其对于初学者来说,在编写调试程序时,掌握断言的使用可以更有效地发现程序中的错误,同时static_assert作为C++11新增的特性,它允许在编译时期...
在Rust编程语言中,`assert_cli`是一个用于命令行接口(CLI)应用程序测试的库。这个库允许开发者轻松地测试他们的CLI应用的输出、返回值以及如何与输入交互。然而,随着时间的发展和社区的反馈,`assert_cli`可能已经...
标题"console2assert"所提及的功能是将常规的`console.log`语句转换为`console.assert`或者用户自定义的断言语法。这样可以将调试信息与代码逻辑结合,使得在非交互式环境下(如测试或生产环境)也能捕获潜在的错误...
在MATLAB中实现二进制转格雷码的程序,主要是利用了格雷码与二进制码之间的转换规则。这个转换过程可以通过一系列数学操作完成,例如模2加法或者位翻转。MATLAB作为一种强大的数值计算和数据可视化工具,提供了丰富...
Node.js中的assert模块是JavaScript中一个非常重要的测试库,它主要用于编写程序的单元测试。通过断言可以尽早地发现和排查程序中潜在的错误。在Node.js中,assert模块作为核心模块之一,提供了一系列用于测试的断言...
3. **自定义类**:为了封装阴阳历转换的功能,可以创建一个自定义的`LunarSolarConverter`类,包含`ToLunar`和`ToSolar`方法,分别用于阳历转阴历和阴历转阳历。 4. **日期格式化**:在输出日期时,C#的`...
断言变压器 为了编译代码,您需要Eclipse和/或Maven,以及Java 8。 要进行编译,请在根文件夹(即包含pom.xml的文件夹)中键入以下内容: mvn compile 生成.jar文件: ... Usage: assert-transformer input
@article{lai2019assert, title={ASSERT: Anti-Spoofing with Squeeze-Excitation and Residual neTworks}, author={Lai, Cheng-I and Chen, Nanxin and Villalba, Jes{\'u}s and Dehak, Najim}, journal={arXiv ...