你真的会使用assert吗?
写这篇博客源于在阅读lighttpd源代码是遇到的一个关于assert应用的疑问。
在阅读lighttpd源代码时,发现比比皆是的对malloc的调用结果进行assert检查,比如:Buffer.c:

buffer* buffer_init(void) {
buffer *b; b = malloc(sizeof(*b));
assert(b); b->ptr = NULL;
b->size = 0;
b->used = 0; return b;
}

这里的assert(b)似乎有问题,实际release版本在运行中难道不会发生malloc返回NULL的情况吗?之后在阅读《Writing Solid Code 》一书时找到了答案。
对assert的基本用法就不再累述了,下面总结一下assert的实际应用的Recommended practice吧:
1、要使用断言对函数参数进行确认
主要有以下情况:
- 指针不是NULL的断言;
- index值或size值不是负值或小于已知限值的断言;这一条也可以这么描述:要从程序中删去无定义的特性或者在程序中使用断言来检查出无定义特性的非法使用
2、每个断言必须在头文件中的函数功能描述的断言部分进行说明(不要浪费别人的时间 ─── 详细说明不清楚的断言 ),例如:
* Asserts:
* 'size' is no greater then LIMIT.
* 'format' is not NULL.
* The function result is no greater than LIMIT.
*/
如果没有断言, 写 “Nothing”:
* Asserts:
* Nothing
*/
(以上的格式也许严格了一些,不过如果真的这么做,对代码的可阅读性会很有帮助)
3、断言和错误校验的区别
正确使用断言,必须要清楚程序错误(program errors)和运行时错误(run- time errors)之间的区别;
- 一个程序错误是一个bug,永远不应该发生。
- 一个运行时错误是在程序运行的任何时候都可能会发生.
断言并不是一种处理运行时错误的机制。例如在需要输入正数的时候,用户输入了一个负数,如果用断言来检测这种情况就不是好的设计。对于这种情况需要用合适的错误检查和恢复处理的代码来进行处理。
再回到lighttpd中对malloc函数的返回值进行assert断言,我觉得也属于这个问题,这应该是一个运行时错误,而不是程序错误;所以,我觉得《C和指针》一书中对malloc返回NULL处理是通过一个错误检查分配器来处理的。
4、断言和bug
断言大致分为前置条件(Preconditions)、后置条件(Postconditions)、不变性条件(Invariants)
如果前置条件不成立,发生Assertion violations,则调用该函数的代码存在bug,需要尽快找到并解决;
如果后置条件不成立,发生Assertion violations,则(函数的)实现代码存在bug,需要尽快找到并解决;
例如:

void doBlah(int x) { assert(x!=0); .... }

这段代码说明这个函数的调用不可能传入参数0,如果发生这种情况,说明调用这个函数的代码存在bug;
以上是自己的一点理解,欢迎高手指正!!!
参考:How to use assertions in C
你真的会使用assert吗?的更多相关文章
- 编程范式 episode 6 实现stack 栈功能_ to do
//既然在这里开始,那就在这里结束. 实现stack 功能 ____coding _using subfunction to focus on the main aim of current func ...
- 简明python教程 --C++程序员的视角(九):函数式编程、特殊类方法、测试及其他
函数式编程 Lambda exec,eval和assert语句,repr函数 lambda语句 用来创建简短的单行匿名函数 print_assign = lambda name, value: n ...
- (原+转)简明 Python 教程:总结
简明 Python 教程 说明:本文只是对<简明Python教程>的一个总结.请搜索该书查看真正的教程. 第3章 最初的步骤 1. Python是大小写敏感的. 2. 在#符号右面的内容 ...
- 笔记|《简明Python教程》:编程小白的第一本python入门书
<简明Python教程>这本书是初级的Python入门教材,初级内容基本覆盖,对高级内容没有做深入纠结.适合刚接触Python的新手,行文比较简洁轻松,读起来也比较顺畅. 下面是我根据各个 ...
- OO的奇妙冒险2
OO的奇妙冒险 ~多线程入门与魔鬼的优化~ 目录 总体分析 作业内容分析 作业内容总结 互测的收获 公测互测bug分析与总结 优化分析 不太正经的个人自嗨 总体分析 公测 中测(基础与进阶): 这一单 ...
- python学习笔记比较全
注:本笔记基于python2.6而编辑,尽量的偏向3.x的语法 Python的特色 1.简单 2.易学 3.免费.开源 4.高层语言: 封装内存管理等 5.可移植性: 程序如果避免使用依赖于系统的特性 ...
- 你真的了解load方法么?(转载)
本文授权转载,作者:左书祺(关注仓库,及时获得更新:iOS-Source-Code-Analyze) 因为 ObjC 的 runtime 只能在 Mac OS 下才能编译,所以文章中的代码都是在 Ma ...
- python学习笔记 - assert用法
[转自]http://blog.sina.com.cn/s/blog_76e94d210100vz37.html 1.assert语句用来声明某个条件是真的. 2.如果你非常确信某个你使用的列表中 ...
- 不加班的实践(1)——这真的该用try-catch吗?
前言 我有个技能,就是把“我”说的听起来特别像“老子”. 以前是小喽啰的时候,会跟领导说“我!不加班.”,听起来就像“老子不加班!”一样.到最后发现,我确实没有把计划内的工作拖到需要加班才能完成,这个 ...
随机推荐
- 快速掌握RabbitMQ(三)——消息确认、持久化、优先级的C#实现
1 消息确认 在一些场合,如转账.付费时每一条消息都必须保证成功的被处理.AMQP是金融级的消息队列协议,有很高的可靠性,这里介绍在使用RabbitMQ时怎么保证消息被成功处理的.消息确认可以分为两种 ...
- Scrum软件开发
Scrum 什么是Scrum Scrum是迭代式增量软件开发过程,通常用于敏捷软件开发.Scrum包括了一系列实践和预定义角色的过程骨架.Scrum中的主要角色包括同项目经理类似的Scrum主管角色负 ...
- Effective Java P2 Item1 Consider static factory methods instead of constructors
获得一个类的实例的传统方法是公共的构造方法,还可以提供一个公共的静态工厂方法(一个返回值为该类实例的简单静态方法), 例如Boolean(boolean 的封装类) public static Boo ...
- 【面试 springMVC】【第四篇】springMVC的一些问题
1.springMVC的工作流程是什么样的 1.用户请求到达 2.DispatcherServlet接收请求,发送给处理器映射器 3.处理器映射器handlerMapping,处理找到对应处理器,返回 ...
- 数据库系统学习(十)-嵌入式SQL语言之动态SQL
第十讲 嵌入式SQL语言之动态SQL 静态SQL 区别变量和属性:高级语言向嵌入式SQL传递变量的方法 动态SQL 动态构造SQL语句是应用程序员必须掌握的重要手段 SQL语句的动态构造示例 根据界面 ...
- Sentinel实现Redis高可用
实现目标: 一主两从,集群起始VIP在master上边,如果当前master挂了,sentinel自动选出一个slave当选master,并把VIP漂移到这台机器,然后把另一台slave指向的mast ...
- HDU 2009 整除的尾数 题解
Problem Description 一个整数,仅仅知道前几位,不知道末二位.被还有一个整数除尽了.那么该数的末二位该是什么呢? Input 输入数据有若干组,每组数据包括二个整数a,b(0&l ...
- Js学习第十天----函数
函数 什么是函数?函数是由事件驱动的或者当他被调用时运行的可反复使用代码块.预计没明确,个人觉得函数就是能完毕一个功能的代码块. 看个案例: <!DOCTYPE html> <htm ...
- Go fsm
package fsm import ( "log" ) type EvtIf interface { GetEvtType() string } type Action inte ...
- 代码调试过程中easy遇到的问题
前两天身体有些不舒服,也没写啥新文章,昨天下了一天的雨.今天阳光明媚,空气也非常新奇.心情大好. 继翻译为什么输出是String而不是Object,今天先写一下调试方面的东西.java中自带的函数调试 ...