assert()

1   #include "assert.h"  


2   void assert( int expression ); 




  assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。 
   
  请看下面的程序清单badptr.c: 


显示代码打印01   #include   


02   #include   


03   #include   


04   int main( void )   


05   {   


06    FILE *fp;   


07      


08    fp = fopen( "test.txt", "w" );//以可写方式打开一个文件,如果不存在就创建一个同名文件   


09    assert( fp ); //所以这里不会出错   


10    fclose( fp );   


11      


12    fp = fopen("noexitfile.txt", "r" );//以只读方式打开一个文件,如果不存在就打开文件失败   


13    assert( fp ); //所以这里出错   


14    fclose( fp ); //程序永远都执行不到这里来   


15      


16    return 0;   


17   } 




   
  使用assert的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。 
  在调试结束后,可以通过在包含#include 的语句之前插入 #define NDEBUG 来禁用assert调用,示例代码如下: 


显示代码打印1   #include   


2   #define NDEBUG   


3   #include 




   
  用法总结与注意事项: 
  1)在函数开始处检验传入参数的合法性 
  如: 
   


显示代码打印01   int resetBufferSize(int nNewSize)   


02   {   


03   //功能:改变缓冲区大小,   


04   //参数:nNewSize 缓冲区新长度   


05   //返回值:缓冲区当前长度   


06   //说明:保持原信息内容不变 nNewSize<=0表示清除缓冲区   


07   assert(nNewSize >= 0);   


08   assert(nNewSize <= MAX_BUFFER_SIZE);   


09      


10   ...   


11   } 




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


显示代码打印01   //复制不重叠的内存块   


02   void memcpy(void *pvTo, void *pvFrom, size_t size)   


03   {   


04   void *pbTo = (byte *) pvTo;   


05   void *pbFrom = (byte *) pvFrom;   


06   assert( pvTo != NULL && pvFrom != NULL );   


07   while(size - - > 0 )   


08   *pbTo + + = *pbFrom + + ;   


09   return (pvTo);   


10   } 




   
  assert 不是一个仓促拼凑起来的宏,为了不在程序的Debug 版本和Release 版本引起差别,assert 不应该产生任何副作用。所以assert 不是函数,而是宏。程序员可以把assert 看成一个在任何系统状态下都可以安全使用的无害测试手段。 
   
  很少有比跟踪到程序的断言,却不知道该断言的作用更让人沮丧的事了。你化了很多时间,不是为了排除错误,而只是为了弄清楚这个错误到底是什么。有的时候,程序员偶尔还会设计出有错误的断言。所以如果搞不清楚断言检查的是什么,就很难判断错误是出现在程序中,还是出现在断言中。幸运的是这个问题很好解决,只要加上清晰的注释即可。这本是显而易见的事情,可是很少有程序员这样做。这好比一个人在森林里,看到树上钉着一块“危险”的大牌子。但危险到底是什么?树要倒?有废井?有野兽?除非告诉人们“危险”是什么,否则这个警告牌难以起到积极有效的作用。难以理解的断言常常被程序员忽略,甚至被删除。 [Maguire 1993] 
   
  以下是使用断言的几个原则: 
   
  (1)使用断言捕捉不应该发生的非法情况。不要混淆非法情况与错误情况之间的区别,后者是必然存在的并且是一定要作出处理的。 
   
  (2)使用断言对函数的参数进行确认。 
   
  (3)在编写函数时,要进行反复的考查,并且自问:“我打算做哪些假定?”一旦确定了的 
  假定,就要使用断言对假定进行检查。 
   
  (4)一般教科书都鼓励程序员们进行防错性的程序设计,但要记住这种编程风格会隐瞒错误。当进行防错性编程时,如果“不可能发生”的事情的确发生了,则要使用断言进行报警。 
  
ASSERT ()是一个调试程序时经常使用的宏,在程序运行时它计算括号内的表达式,如果表达式为FALSE (0), 程序将报告错误,并终止执行。如果表达式不为0,则继续执行后面的语句。这个宏通常原来判断程序中是否出现了明显非法的数据,如果出现了终止程序以免导致严重后果,同时也便于查找错误。  


ASSERT只有在Debug版本中才有效,如果编译为Release版本则被忽略。  
--------------------------------------------------------------- 


ASSERT宏定义如下  




显示代码打印1 #define ASSERT(f)   


2 do  


3 {   


4        if (!(f) && AfxAssertFailedLine(THIS_FILE, __LINE__))   


5                AfxDebugBreak();   


6 } 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继续调试。 
文章出处:飞诺网(www.diybl.com):http://www.diybl.com/course/3_program/c++/cppjs/20071111/85534.html
### Python 中 `assert` 的基本用法 在 Python 中,`assert` 是一种调试工具,用于确认某个条件是否为真。如果条件为假,则抛出 `AssertionError` 异常[^1]。它的语法如下: ```python assert condition, optional_message ``` - **condition**: 这是一个布尔表达式。如果该表达式的值为 False,则会引发异常。 - **optional_message**: 可选参数,提供额外的信息以便于调试。 #### 示例代码 以下是一些常见的 `assert` 用法示例: ```python def divide(a, b): assert b != 0, "除数不能为零" return a / b print(divide(10, 2)) # 正确执行 # print(divide(10, 0)) # 抛出 AssertionError: 除数不能为零 ``` --- ### 解决方案:为什么 `assertIn` 方法无法正常工作? 根据引用内容[^1],如果你尝试使用 Python 2.7 版本中的新断言方法(如 `assertIn`),却遇到 `AttributeError` 错误,可能是因为这些方法仅存在于 `unittest.TestCase` 类中。这意味着它们并非全局可用的内置函数,而是特定于单元测试框架的一部分。 为了正确使用这些方法,请确保继承了 `unittest.TestCase` 并在其上下文中调用这些方法。例如: ```python import unittest class TestExample(unittest.TestCase): def test_inclusion(self): self.assertIn('a', 'abc') # 测试字符串'a'是否包含在'abc'中 if __name__ == '__main__': unittest.main() ``` 如果不希望依赖 `unittest` 模块,也可以手动实现类似的逻辑: ```python def custom_assert_in(subset, superset, msg=None): if subset not in superset: raise AssertionError(msg or f"{subset} 不在 {superset} 中") custom_assert_in('a', 'abc') # 成功 # custom_assert_in('d', 'abc') # 抛出 AssertionError: 'd' 不在 'abc' 中 ``` --- ### Spring Framework 中的 `Assert` 工具类 除了 Python 的原生 `assert` 关键字外,在 Java 开发领域,Spring 提供了一个名为 `org.springframework.util.Assert` 的实用工具类[^2]。这个类包含了多种静态方法,可用于验证输入参数的有效性。以下是几个常用的方法及其用途: | 方法 | 描述 | |--------------------------|----------------------------------------------------------------------| | `Assert.notNull(obj)` | 确保对象不为 null | | `Assert.hasText(str)` | 确保字符串非空且至少包含一个非空白字符 | | `Assert.isTrue(condition)`| 确保给定条件为 true | 示例代码: ```java import org.springframework.util.Assert; public class Example { public static void main(String[] args) { String name = "John"; Assert.hasText(name, "姓名不能为空"); Integer age = 25; Assert.isTrue(age >= 18, "年龄必须大于等于18岁"); } } ``` --- ### C/C++ 中的 `ASSERT()` 宏 在 C 和 C++ 编程语言中,`ASSERT()` 是一个常用的调试工具,主要用于检测程序运行过程中可能出现的错误状态[^3]。它的工作原理类似于 Python 的 `assert`,但在生产环境中通常被禁用以提高性能。 #### 核心特性 - 条件检查:只有当表达式的结果为 false 时才会触发断言失败。 - 调试辅助:允许开发者快速定位问题所在。 - 发布优化:在 Release 构建配置下自动移除所有断言语句。 #### 实现方式 标准库头文件 `<assert.h>` 或 `<cassert>` 提供了支持。下面展示如何定义自己的简单版断言机制: ```c++ #include <iostream> #define CUSTOM_ASSERT(cond) \ do { \ if (!(cond)) { \ std::cerr << "Assertion failed: " << #cond << "\n"; \ abort(); \ } \ } while (false) void exampleFunction(int value) { CUSTOM_ASSERT(value > 0); } int main() { exampleFunction(-1); // 触发断言失败 return 0; } ``` --- ### 单元测试框架中的断言方法 许多现代编程语言都集成了丰富的断言功能,特别是在单元测试场景下。例如,在 .NET Core 的 NUnit 库中,存在一系列专门设计用来比较不同类型的值或结构体的断言方法[^4]。 | 方法 | 功能描述 | |-----------------------|-------------------------------------------| | `IsTrue(expression)` | 验证布尔表达式是否成立 | | `AreEqual(expected, actual)` | 判断两者的值是否完全一致 | | `IsNotNull(object)` | 确认传入的对象实例不是 null | 实际应用案例: ```csharp using NUnit.Framework; [TestFixture] public class SampleTests { [Test] public void ShouldVerifyEquality() { var result = CalculateSum(2, 3); Assert.AreEqual(5, result, "加法运算结果有误"); } private int CalculateSum(int a, int b) => a + b; } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值