免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 77h2_eleven
打印 上一主题 下一主题

[函数] 大家在项目代码中会大量使用断言么?  关闭 [复制链接]

论坛徽章:
0
121 [报告]
发表于 2008-10-10 17:25 |只看该作者

回复 #120 alickguo 的帖子

120楼 发表于 2008-9-9 21:45   
用assert还是比较温柔的了,在偶的模块对外接口曾是这么干的(偶的模块非UI).

if (不是偶要的参数输入){
     trace_sp();     /* 给个堆栈trace,看看是哪个丫的调的我的模块 */
     dump_param_list( ... ) /* 抓个现形 */
     assert(0);      /* assert一下,知道哪行问题 */
     panic();          /* 偶们的系统assert是不会panic的,因此主动死给你看,谁让你丫不按接口定义传参!! */
}

不过上面的代码在模块集成完毕后就干掉了,只给个assert~
============
牛X注释!!

论坛徽章:
0
122 [报告]
发表于 2008-10-11 14:56 |只看该作者
好像用的比较少哦,
正式提交给用户的都是非debug版本,再说又很多bug很难复现的,日志系统不可少,
另外程序在关键部件不能panic,不知道各位是怎么处理的,assert不是挂掉了吗?
自己有时候还是if处理一下,看看怎么处理比较合适就怎么处理,自己处理出错肯定是需要的,光assert不行
有些人说程序调试一下不就知道问题出现在什么地方了吗?实际上东西交出去之后,无论是系统,还是,一般的嵌入式的小系统
有时候没法恢复现场的,客户乱搞,东西都没有了,还是只能信赖自己的程序。

[ 本帖最后由 ailantian 于 2008-10-11 14:58 编辑 ]

论坛徽章:
0
123 [报告]
发表于 2008-10-19 15:34 |只看该作者
我一般用在分配内存后.其它地方较少使用.

论坛徽章:
0
124 [报告]
发表于 2008-10-28 10:11 |只看该作者
这个贴的讨论主要在
http://bbs.chinaunix.net/thread-25356-1-1.html

研究的很大程度上是一个问题.

论坛徽章:
0
125 [报告]
发表于 2008-10-28 10:32 |只看该作者
实际上,直接CRASH是一个追求的最高目标. 可惜由于硬件软件,体系结构等限制, 远达不到.

比如,strcpy(d, s), 如果d是一个被free(d)的地址, 系统往往也能工作. 但这里实际是一个巨大的恶劣的BUG. 无法CRASH的原因是硬件对内存的保护是按页的, 无法按字节.

有BUG就直接CRASH应用是一个目标. 不能完全达到.

我原来是修理电视的. 最好的故障是什么? 是子系统全坏掉. 最恶劣的故障是系统神经病似地故障---时断时续,时大时小,变化莫测.---- 对于软件说也一样.

-------------
实际上, 编译系统和OS配合, 故意将地址NULL(0)留出来并设置为内存保护段. 当程序使用NULL中内容时候, 让程序CRASH掉. 目的就是为了DEBUG, 而且是非常容易地DEBUG.

所以可以说, strcpy和许多库FUNCTION看似没有检查参数指针是否是NULL, 其实是系统替你检查了. 好处是, 不影响速度. 同时有可以给用户报了错误. 你想呀, strcpy是多么底层的被大量调用的, 检查那东西浪费了效率. 程序中的废话在高层地方出现对效率影响很小, 在底层出现影响很大.

BTW, strcpy的库绝大多数不是LZ那样用C编的, 而是用汇编指令(许多CPU都用专门移动,COPY串的指令). C编的效率要低许多许多.

-------------------------------------------
还有, 你编程序应该设计的结果是:
有BUG就CRASH, 但CRASH后不影响没有遭遇BUG的部分的正常运行. 实际上UNIX给了你这个机制, 就是进程.

---------------------------------------------
还有,
不要将应用程序的CRASH(Segmentation fault后推出运行)理解成汽车撞树,飞机CRASH地面.

实际上, 这里发生的一切都在OS 的掌控之下,检查出问题了,让你的程序停止下来, 温柔地停下来.
有点相当与你靠驾驶执照时候, 交通警察是考官, 你犯了错误后的情况.

而撞树相当与OS没有检查,错误的程序还在继续,直到系统不动了,或错误数据产生了.DOS原来许多地方就如此.

论坛徽章:
0
126 [报告]
发表于 2008-10-28 12:56 |只看该作者
用断言是为排除发布之前的BUG。

论坛徽章:
8
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:58技术图书徽章
日期:2013-12-04 10:48:50酉鸡
日期:2014-01-03 10:32:30辰龙
日期:2014-03-06 15:04:07
127 [报告]
发表于 2008-10-28 15:43 |只看该作者
呵呵,在另外那个帖子中讨论时还针对神七飞船写了个案例,不过感觉前面的帖子已经说清楚了,就没有发。

大家在学校学的东西,往往都是一些局部的、分离的算法,很少有站在大局角度通盘考虑的;并且国内教授自己多数也没什么实践经验,教不好错误处理很正常。


案例:

神七飞船载重有限,因此减速火箭只能在着陆前5秒打开(因为燃料就这么多);实际上,这个数据考虑了最不利状态下姿态控制的需要并留有1秒的余量。

现在,要求是设计一个能保证安全着陆的程序。
这个程序要读取飞船当前的姿态、速率以及高度、风向、风速等信息,然后实时控制飞船着陆。


现在,考虑这样一种情形: 假如上级调度模块在宇宙空间的恶劣环境下,因射线击中存储器某单元造成状态翻转,致使栈写越界——于是着陆控制模块发现,指向飞船姿态数据区的指针被改写成0了。

当然,这种情况是无法事先预估到的。怎么办?


如果返回错误码,是可以避免因引用无效内存而崩溃;但被破坏的栈可不会自动恢复。
很可能,这个return指令会因为栈中返回地址也已经被破坏,而使得代码跳到一个未知的位置继续执行——也许飞船都撞到地面了,这段跑飞的代码还没回来;减速火箭自然也就不可能打开。

于是,飞船撞毁,宇航员必死无疑。



正确的做法只能是——发现异常就crash!

PS:介绍个新概念:watch-dog(搞嵌入式的应该很熟悉这个)。
——watch-dog的原理就是:要求程序必须安排合适逻辑定时清零计数器(报告状态正常);一旦计数器到时没有清零,就立即reset系统(相当于crash)。因为此时程序可能已经跑飞了(当然,也可能是时序没算对)。
——当然,watch-dog的周期不可能太短,否则对系统性能消耗过大;但太长又可能导致反应不够灵敏,这是必须根据实际折中考虑的。

实时系统的重启速度相当快。玩数码相机的应该有所体会——我的那个好像说是0.0x秒吧。

于是,由于设计上预留的1秒缓冲,若能立即crash的话,系统可以容忍连续10次失败仍能保证飞船安全着陆——连续2次或3次失败后自动切换备用系统等等设计也才有了发挥空间。

可见,crash不是洪水猛兽。它是构建真正稳定的系统的不可缺少的一环(当然,普通如word等软件,出错直接崩溃提交就行了,没必要设计机制保障7*24的绝对安全性)。


相反,如果仅仅返回个稀里糊涂的错误码,系统跑飞被watch-dog抓到还算好(但也已经耽误不少时间了),万一跑飞的那个地方刚好是刷新watch-dog的逻辑,岂不完蛋?

搞出这种飞机的,有几个脑袋够M249打眼?

——————————————————

说到底,这纯粹是个态度问题。

都知道捕获所有异常并忽略是完完全全的混蛋;但每个错误都要查清来龙去脉却也不是易事——尤其是在缺乏责任心的人那里。

所以,“聪明”人就有了发挥其“中国式智慧”的机会了:有错,我知道,我也报告了——别人不处理怪他。
别人?
别人也不是傻蛋。你报告我也报告,说不定问题绕了一圈又回你手里了。
——无所谓,反正程序还能跑。

最后,代码中充斥着各种各样稀奇古怪的错误,到处都是错误码,人人都在写日志——反正正常流程能走通,交得了差。

你说什么?空指针不准确确定原因和影响范围,稀里糊涂返回错误码可能导致程序跑飞?
跑飞就跑飞。又没崩溃。
反正到处都是检查,到处都是容错,说不定飞着飞着它就又飞回来了——像蟑螂一样,这系统命硬着呢。

你说这样说不定哪天就撞到格硬盘刷bios的那块代码了?
没事,那才多大点概率。我可以保证99%,至少也有90%的情况下跑不到那里。

总之,不崩溃才是王道——很明显,这种容错容的跑飞说不定还能跑回来的系统,你哪里知道崩溃时已经跑飞多少遍了!

一旦崩溃——苍天啊!这问题谁有本事定位!!

说不得,整个系统大返工,每个函数每个参数的——不是查故障啦,没法查——加容错代码。
——口号是:一定要保证程序跑飞后还能跑回来!
(当然,这时候逻辑是否正确、数据有无丢失就顾不得了)

显然,随着程序的崩溃,搞出这种垃圾的程序员怎么可能不恐惧到崩溃。
——我理解这种病人;但不认为他们值得同情。




一言以蔽之:一群没责任心的懒蛋想偷懒,结果越偷懒越是忙得不可开交;最终代码写了5000行,其中容错逻辑倒有3000多行——其中1800行是为了给那2000行代码加容错逻辑;另外800行是给1800行容错代码加的容错;剩下的则是容错代码的容错的容错(的容错……)。

越容越复杂,错也就越多;错越多越无计可施,只能继续容错,于是系统就更复杂更不可调试……

——————————————
assert的思想本质就是: 出错了,一定要立刻崩溃(报告),千万别拖来拖去搞出先跑飞再崩溃的飞机。
只有这样,排错才会轻松惬意——跑一跑,根据assert报的行号直接过去修改问题就是,几乎不需要什么代价。
assert越多、越准确,错误就被限制得越死;一旦触发到,问题也就越好解决。

至于发行版assert自动失效(这已经是内建于c/c++标准库的机制了),原因仅仅是不希望为无用的东西付出运行时效率而已(无用二字正体现了对测试流程的自信,同时也显示出这种系统有多好测)。
——这种境界,显然不是没这样做过的人所能理解的。

论坛徽章:
0
128 [报告]
发表于 2008-10-29 23:37 |只看该作者
断言在很多地方不适用,比如我是不用的

论坛徽章:
0
129 [报告]
发表于 2008-11-17 11:49 |只看该作者
除了那些极端的发现异常就需要crash的程序外,
使用断言的最大用途还是自动化测试吧,编写好测试用例和预想结果,并存档,当代码优化或重构后跑一下,以验证新的程序和旧的程序在行为上没有改变。

论坛徽章:
0
130 [报告]
发表于 2008-11-18 10:05 |只看该作者
我样要求,特别是写日志等!!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP