我的女朋友漏电了–论C++中的失败(failure),缺陷(bug)和异常(exception)
先做个广告置入,如果喜欢这篇文章,你可以到 zhaoyan.website/blog 去查看于此类似的C/C++文章。
我承认有点标题党了,不过这真的是一篇写软件的文章,所以如果你已经抽出了一张面巾纸,那么趁早再把它完美的放回去。这篇软件文章很软,源代码不多,而且大部分都是伪代码。所以很适合所有人看。我特别推荐年轻的初学者,把纸巾放回去后,继续看下去。如果把这几个概念理清楚,对未来的工作非常有帮助。
先说失败(failure)。常见的软件的失败主要分为三种,编译失败,运行失败,结果失败。下面通过一个程序的例子来说明:
你可以把编译失败理解成世界上最聪明的一堆程序员在帮你审核你的代码。如果审核失败,他们会提醒你在造成严重错误之前修改你的问题。单从这一点看,C++也比一些解释性的语言更加安全。例如源码中你想把变量l1修改一下。但是由于笔误写成了ll。C++的编译器会对你大吼的。但是Python一声也不吭,看你运行时候的笑话。
运行失败是指你已经有了可执行程序,当你运行它的时候,它crash了,挂了,死了,kick the bucket了。一个你最经常看见的输出就是访问越界内存带来的Segmentation Fault。所以请记住:男人头,女人腰,还有越界内存。这三样东西永远不要摸,否则会挂掉。
比起结果失败,你会发现运行失败是多么美好的一件事。上面的if语句是C++中非常著名的一个结果失败的例子。你的程序编译正常,运行正常,就是结果不对。而且你还不知道原因所在。另外一个常见的原因就是C++的数值计算溢出。这在C++中是非常著名的“未定义”。 C++标准委员会乐观的认为如果我“未定义”,那么天才的编译器程序员会发明一种最聪明的方法来解决这个问题。但是实际的情况是:天才的编译器程序员是最懒惰的程序员!如果你“未定义”,那么他们就什么也不干。结果就是到底发生什么,鬼知道!!!
如果你还没看懂,没关系!我再给你举了生活的例子。一个程序员根本就没有女朋友。这个就类似于编译时失败。一个程序员有个女朋友,但是他第一天就去摸人家女孩子的腰。有些地方还真是和尚摸得,你却摸不得,结果女朋友愤然离去,这可以对应运行时错误。最后一种情况当然就是结果错误了。程序员有了一个漂亮的女朋友,第一天他去摸人家的腰,女孩子不仅没有生气,还娇羞的把头靠在程序员的肩旁上,对他说:“讨厌了,你刚才把人家摸怀孕了啦!”
现在的问题就是:如何能尽早的发现女朋友是否怀孕?不对,我说错了,我是想说如何能够更早的发现失败?
首先,常见的失败的原因主要有两种,一种是缺陷(bug),另外一种是异常(exception, error)。好多人搞不清楚,所以我上段代码:
请注意,我说的缺陷就是bug的含义。也就是常说的虫子。缺陷主要有两种,设计缺陷和实现缺陷。上面的代码中,用名字来做为查找键值就是一种明显的设计缺陷。如果你在办公室喊一声“狗蛋”,会有好多同事答应的。另外一种实现缺陷我们上面介绍过,key==“Yan”写成了“key=Yan”。这些都会造成程序的失败。
那么我们如何能尽早的发现bug呢?一个很牛逼的工具就是unit test。不过C++也提供另外一个有力的工具,那就是assert。Assert用法是最简单的。下面我们看看它是如何发现我们的缺陷的。
Assert的基本理念可以应对成一句话:“反常必有妖”。上面这段代码的含义是如果发现Yan赚的钱超过了20万,那程序一定是哪里出现问题了。就像你发现你的名字出现在福布斯富豪榜上了,那富豪榜一定是印错了。你最好复查一下计算薪水的代码。如果你再阅读一下上面计算salary的代码,你就会发现是重名的设计缺陷和if的实现缺陷才让Yan的salary那么多。
关于assert,有三点需要说明,第一就是在哪里放assert和用assert验证什么? 一个基本的原则就是函数的各种输入和输出值,但是具体上则完全是根据具体的问题和程序员的经验。你可以把assert想象成传感器。要检验一辆车的质量,一个有经验的工程师知道哪里需要放传感器,用传感器检测什么。而工程师的女朋友会发现:这个颜色我不喜欢!
关于assert 的第二点就是在程序发布版中,assert是失效的。这个很好理解。一个车出厂前才需要用各种传感器来发现各种缺陷,一但发现缺陷,就应该找到缺陷的原因并修正它,直到零缺陷,你才应该把车出厂去买才对。如果用户去买车,发现车上都是传感器。这会影响用户的速度和体验;同时就算是用户发现车漏油这个问题,你让普通用户做什么呢?所以说assert只是工程师用于产品出厂前检测缺陷的,而不是用于最终产品的。当然,零缺陷只是传说,所以车厂有召回,软件公司有补丁。
Assert的第三点是现在c++支持static _assert了。它可以在编译的时候就发现问题,这印证了我前面说过的,编译失败要好于运行失败。
现在我们回来看看计算薪水的代码,看看OpenFile这一段,这里并不是缺陷,而是会发生异常。文件打不开有太多原因,权限不够,名字不对,别人给删掉了。所有这些原因都不是我们的程序能完全控制的。虽然这造成了程序的失败,但是这既不是设计缺陷,也不是实现缺陷,而是一种异常。
对于异常,我们应该用try catch捕捉到这种异常,然后根据上下文做出正确的反应。常见的异常多发生在IO,网络链接和用户交互上。它和assert一样,如果要用好很大程度上取决于具体的问题和程序员的经验。与assert不同的是,它也必须存在于产品的发布版本中。在车的例子中, 车漏油是缺陷,但是车胎扎了就是一种异常。在平时使用的时候,你也应该时刻准备着捕捉到这种异常,并做出正确的反应。这是它和缺陷最大的不一样的地方。
没看懂吗?没关系。让我们继续程序员和女朋友的故事吧。我们上文提到的程序员自从把女朋友摸怀孕后有点怕怕了。他决定从日本买一个型号为“苍井-玛丽亚”的女朋友。拿到货后很快发现女朋友不仅漏气,而且漏电!漏气这个事,明显属于异常范围的。因为即使正常的使用,漏气也会正常地发生。所以一般厂家会提供一些胶水来应对这种情况。
但是漏电这明显是一个bug,厂家是应该用传感器在出厂前就发现并修正这一问题的。也就是说厂家是不应该把这一产品出厂来买的。你需要向厂家报告这一缺陷(bug)。正常的情况下,你会收到厂家的教科书式的回复:“It’s not a bug, It’s a feature!”。我还真的承认。女朋友漏电这个事,人家说是feature(特性),Make sense(没毛病)!
异常是一个很大的topic,感兴趣的可以查看我的两本书《C语言点滴》和《Drop of knowledge of C++》 。里面有很多的关于异常的介绍。
从程序员和女朋友的故事中,我希望你能记住以下几点:
1)编译失败好于运行失败,运行失败好于结果失败。
2)失败通常由缺陷和异常造成。
3)对于缺陷(bug),用assert和单元测试在开发期间尽早发现并修正。
4)对于异常(exception),用try catch 在产品使用的全程捕捉并处理。
5)程序员就不应该找女朋友!
本文摘自异步社区,发表人:zhaoyan,作品《我的女朋友漏电了–论C++中的失败(failure),缺陷(bug)和异常(exception)》未经授权,禁止转载。
推荐阅读
长按二维码,可以关注我们哟
每天与你分享IT好文。
在“异步图书”后台回复“关注”,即可免费获得2000门在线视频课程
点击阅读原文,查看更多内容
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
程序员们都他妈给我笑~裤子都脱了你让我干这个?
一直以来 黑程序员都是一项为人民群众喜闻乐见的娱乐活动 我们不仅黑程序员 程序员也喜欢自黑 人们对程序员的印象一般来自两个地方 影视作品和段子手 前者宣传的程序员往往很酷 而后者揭露的程序员往往很挫 和网上各位段子手的说法不一样 我一直觉得 在骨子里面 程序员都是一群调皮的小朋友 并且拥有善良的心和蓬勃的生活激情 更重要的是 他们普遍都耿直真诚不会撒谎 下面来看看 这样有趣的一群人 有什么话是会引起他们不适的呢? @ZH “这个活儿挺简单的,用不了多久就能搞定了。” (you can you up啊!) @蛋哥 “哟,又在写BUG啊?” (才没有呢!你才在写BUG!你全家都在写BUG嘤嘤嘤!) @DQ睿哲 01 “这个应该很简单吧?“ ”为什么淘宝都能做到,你做不到?” (程序员:我也想知道。) 02 下班了,故意从程序员边上飘过。 淡定的来一句:“哟,还在改 bug 呢。” 看着程序猿难过的眼神。 再加一句:“加油!我先下班了啦~” 03 “尽快做完,OK?” (程序员:用邮件发这句话杀伤力更大……) 04 “你先大概开发一个,我再提需求。” (程序员:请问,什!么!叫!大!概!) ...
- 下一篇
教你一些MySQL数据库入侵及防御方法(有书送)
在针对网站渗透中,很多都是跟 MySQL 数据库有关,各种 MySQL 注入、MySQL 提权、MySQL 数据库 Root 账号 webshell 获取等,但没有一个对 MySQL 数据库渗透较为全面的总结。 针对这种情况我们开展了研究,但技术的进步永无止境,思想有多远,路就可以走多远,在研究 MySQL 数据库安全之余,我们也对 MySQL 如何通过 msf、sqlmap 等来进行扫描、漏洞利用、提权、MySQL 密码破解和获取 webshell 等进行了详细研究。 一、MySQL 信息收集 1、端口信息收集 MySQL 默认端口是 3306 端口,但也有自定义端口,针对默认端口扫描主要利用扫描软件进行探测,推荐使用: iisputter,直接填写 3306 端口,IP 地址填写单个或者 C 段地址; Nmap 扫描 Nmap -p 3306 192.168.1.1-254。 特定目标的渗透,可能需要对全端口进行扫描,可以使用 Nmap 对某一个 IP 地址进行全端口扫描,端口扫描软件还有 sfind 等 DOS 下扫描的工具。 2、版本信息收集 msf 查看版本信息“auxili...
相关文章
文章评论
共有0条评论来说两句吧...