断言

  讨论断言(assertions),一个你兵器库内非常强大的工具。以assert为基础,我们建立一个更强大的工具,帮助你建立更好的程序。我们很快就能看到,断言不仅是简单的工具/宏/函数。这是一种生活方式,一道深深的鸿沟把程序员们分成两类:了解,和不了解断言的力量。

 

Assert(cool);

       那么,断言到底包含了什么?为什么你要重视断言?你什么时候需要用到断言,并且同样重要的,什么时候你不想要用到断言。

       我的看法是断言(例如用标准assert宏表示)是一个最最简单强大的工具来保证程序的正确性。断言的威力通常被低估了,至少在我参与的项目中是这样。可以这样说:一个项目的成功条件是开发人员如何有效地在代码中使用断言。

       断言的一个重要特性是它只在调试方式中产生代码(当NDEBUG宏没有定义时),所以它某种意义上是“免费”的。这让你测试看上去非常明显的事实,本来检测这些是一种效率上的浪费,但在发布模式中效率上没有浪费,所以你在插入大量断言时心理上不会感到不舒服。

       哲学家说事实胜过假想,事实比我们的头脑所能设想的更为复杂。这在软件开发中当然也适用。有着无数的例子,本来“绝对不可能触发”的断言事实上被触发了。历史一次次重演:“这个值当然是正的!那个指针明显不是空的!这个数组?我敢打赌毫无疑问是排序的。为什么要反复再核对呢?”如果你是新手,你认为你写些assert是在浪费你的时间,但它们的触发可以救你的命。这都是因为软件开发很复杂,并且在正在修改的程序中任何情况都有可能发生。断言检查你认为“明显为真”的地方实际上是为真。

       一个断言的微妙方面是它越“笨”,当它被触发时所能带给你的信息就越多——并且它也就越有价值。这是因为根据信息的理论,事件中的信息随着事件发生概率的提高而减少。某个assert越不可能触发,当它触发时带给你的信息也就越多。比如,当调试一些不带断言的代码时,你可能首先检查更明显的失败可能原因,你会只在晚些时候(晚些,可能是“在排除所有可能解释后的半夜时分”)才考虑到那些“不可能发生”的条件。

       所以什么时候使用assert,并且什么时候使用真正的指明一个错误的运行时检查?不管怎样,assert用来指出错误,但存在其他方法也能指出错误。你该如何决定哪种情况下使用何种错误报告方式呢?

       有一种有效的测试手段来区分哪种场合你需要使用assert,什么时候需要使用真正的错误检查:你对可能发生的情况使用错误检查,即使这些情况不太可能发生。你只对你确信在任何情况下都不可能发生的情况使用assert。一个失败的断言总是指明一个设计上或程序员的错误——不是一个用户错误。

       断言检测的情况理论上几乎总是可以在编译时检测。但仅仅是理论上。验证某些事情实际上是行不通的,比如不可接受的编译时间,缺乏源代码等等。,

       另一方面,你不会用断言检查可能失败的函数返回值。你不会用assert来确保malloc工作正常[5],创建成功一个窗口,或者启动一个线程。但是你能够用assert来保证API如文档中所写的那样工作。比如,如果某个API函数的文档说它只返回一个正值,但由于某种原因你觉得它可能存在问题,你就需要写一条assert。


实现断言

       标准提供的assert有着非常简单的实现,类似于下面:

  1. //来自于标准包含文件cassert或assert.h
  2. #ifdef NDEBUG
  3.        void __assert(const char*, const char*, int);
  4.        #define assert(e) ((e) ? (void)0 : __assert(#e, __FILE__, __LINE__))
  5. #else
  6.        #define assert(unused) ((void)0)
  7. #endif

       __assert辅助函数在标准错误输出流中显示一条错误信息并且通过调用abort()来中断程序。各种不同实现可能存在不同,比如,Microsoft Visual C++显示一个对话框窗口来让你有机会进入调试器查看源代码。你仍旧不能忽略断言然后继续执行原有操作——当你在调试器中继续操作时仍旧会调用abort()(有一点让人遗憾——你就象俄耳甫斯,在欧律狄刻被带回冥府前才看到她。但有方法克服这个情况——对Microsoft Visual C++用户而言而不是对俄耳甫斯[6]

       用abort()终止程序过于粗鲁。很多情况下,你可能想要忽略一个特殊断言,因为你觉得它是无害的。而且某些操作系统和调试器允许你进入你的源代码来追踪发生的问题,同样在这种情况下你不需要abort(),相反你需要有选择是否继续跟踪程序代码的自由。

       这也是为什么通常建议是你写自己的断言机制。


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值