bug的本意是指昆虫、小虫、损坏、缺陷等意思,在互联网时代还有一种引申意义,用来形容某人/物超乎想象的厉害,那简直就是开挂的人生,系统的bug!

一般地,在码农的世界了,bug是在电脑系统或程序代码中隐藏着的一些未被发现的缺陷或问题,可以简称为程序缺陷。从广义上看,还包括软件需要改进的细节、或与需求文档存在差异的功能实现等等。

bug 是如何与程序缺陷联系起来的呢?

Bug的由来

时光回溯到一台计算机可以装满整个房间的时代,大约在1945年9月9日,Grace Hopper发现了Harvard Mark II 计算机的第一个bug。Grace Hopper是数据处理方面的专家,在1952年为UNIVAC开发了第一个编译器,能够把人读得懂的高级语言翻译成计算机能够识别的机器语言。

那一天,Grace Hopper对Harvard Mark II设置好的17000个继电器进行编程后,技术人员正在进行整机运行,它突然停止了工作。于是他们爬上去找原因,发现这台巨大的计算机内部一组继电器的触点之间有一只飞蛾,这显然是由于飞蛾受光和热的吸引,飞到了触点上,然后被高电压击死。死去的飞蛾被夹扁在触点中间,从而“卡”住了机器的运行。

所以在报告中,Grace Hopper用胶条贴上飞蛾,并用“bug”来表示“一个在电脑程序里的错误”。后来,人们在电脑系统或程序代码中隐藏着的那些未被发现的缺陷或问题,也叫“bug”,同时 把排除程序故障叫DEBUG,这一“称呼”成为计算机领域的专业术语。

BUG和DEBUG的中文译为“缺陷”和“调试”。“缺陷”可能更反映事物的本质,因为“bug”是从外面爬进去的,并非程序本身有问题。而程序本身存在的问题,是程序原来就具有的。

程序代码中Bug的产生原因

一般地,在程序设计中的术语, Bug是在软件运行中因为程序代码本身有错误而造成的功能不正常、体验不佳、数据丢失、非正常中断、死机等现象。

Bug 的产生原因多种多样,千奇百怪,例如:

  • 改错了文件

  • 改对了文件,但放错了位置,或者根本忘了保存

  • 改对了文件但没有重新编译

  • 认为把那个条件变量开启/关闭了,但实际上弄反了

  • 运行了错误的版本

  • 改正了问题,但忘了提交

  • 改正了问题,也提交了,但其他代码都依赖于之前有问题的版本

......

软件系统是一个丰富多彩的世界,总有Bug在里面飞来飞去。任何软件在发布时都不可能是绝对的零Bug,因为谁都不敢保证,自己写的代码没有任何问题。

bug的生命周期和分类

实际上, bug的生命周期可能是这样的:

产生-->被发现-->被解决或者变成了另一个bug。

但是从软件工程尤其是QA的角度看,任何一个bug的一般生命周期包括这样几个阶段:

新建-->指派-->已解决-->待验-->关闭

如果等待检验的bug在验证时没有解决好,则需要重新打开bug,开启循环并继续指派。

由于bug众多,我们在fix bug的时候往往本着要事优先的原则,处理那些影响较大的bug,这需要根据bug 的严重程度分类,例如:critical,major,minor,de-effeicency,也就是所谓的P0/P1/P2/P3, 当然粒度也可以分得更细或者粗一点。

根据不同视角,可以对bug有不同的分类,根据bug 所影响的领域分类,QA的测试领域可以参见《程序员眼中的测试》。

另外,bug的数量往往被用来作为衡量软件质量的一个指标。在CMM中规定的软件质量标准如下(Bug个数/千行源代码):

  • CMM1级 11.95

  • CMM2级 5.52

  • CMM3级 2.39

  • CMM4级 0.92

  • CMM5级 0.32

因此,我们往往会在生产bug 和 debug中徘徊,写代码的时间与排错时间的比例有时会高达2:8。既然debug 是我们工作生涯中不可或缺的组成部分,容易混淆的是,debug 尽管在更多时候是一个过程,但有时候指的是一个程序——debugger。

Debugger是个程序

Debugger为一种调试软件,工程师或程序员可以用来验证算法。在一般的硬件设备上,都有着专门用于debug 的接口,在不太遥远的DOS世界里,一行debug 命令可以起到让操作系统初始化的效果。

在windows平台上,WinDbg是微软发布的一款相当优秀的源码级(source-level)调试工具,可以用于Kernel模式调试和用户模式调试,还可以调试Dump文件。

在Linux平台上,一般使用GDB,又称GNU调试器,是用来帮助调试程序的工具。gdb的主要功能如下:

  1. 启动程序,可以按照自定义要求随心所欲的运行程序。

  2. 可让被调试的程序在指定设置的断点处停住。(断点可以是条件表达式)

  3. 当程序被停住时,可以检查此时程序代码中所发生的事。

  4. 还可以改变程序代码,修正一个BUG产生的影响从而测试其他BUG。

很多跨平台的编程语言都一般会有各自的Debugger。PHP的调试方法最基本的是echo或者var_dump。还有就是使用zend debug 或者Xdebug的调试插件。

pdb是 The Python Debugger 的缩写,是Python标准库的一个模块。pdb模块规定了一个Python程序交互式源代码调试器,支持在设置断点(包括条件断点),也支持源码级单步调试,支持栈帧监视,支持源代码列出,支持任意栈帧上下文的随机Python代码估值。它还支持事后调试,并且能在程序控制下被调用。

例如:

>>> import pdb
>>> import mymodule
>>> pdb.run('myfoo.test()')
>>>

也可以命令行调用 python -m pdb myfoo.py 。

总之,Debugger是我们在单机debug中非常重要的工具。但是,对于分布式系统而言,这些debugger 都有着很大的局限,虽然也有一些debugger工具,但多是面向特定系统的。

那么分布式系统的debug 主要依赖什么呢?日志。关于日志的重要性,可以参考《全栈必备 Log日志》。

Debug的原则

不论是单机上的应用,还是分布式系统,debug时遵循问题隔离的原则,便于定位问题。

问题隔离可能是所有debug中最强大的核心原则. 问题是否可重现是非常重要的。如果不能重现这个问题的产生方式, 解决起来会变得异常困难。问题隔离使我们拥有了控制变量。

从空间隔离上看,程序代码中具有不同的库或者框架, 并且可以包含许多同事的提交, 其中, 可能有一些已经不再在这个代码库上工作了。问题隔离有助于消除问题的非必要部分, 以便专注于一个解决方案. 问题隔离的目的是弄清楚是发生冲突的根本原因,了解是否存在竞争条件。

从时间隔离上看,避免一次性的大量修改,越少改动代码越好,这样有助于发现问题。连续反馈的一致性结果越多, bug的跟踪就越容易。所以在调试时, 尽量不要安装任何新的软件或组件, 或者引入新的依赖。如果发现每次静态输入却返回了不同的错误, 应该马上提高警惕, 并且全力解决它。

Debug 时的一些雕虫小技

通过二分法去定位问题是Debug的一般方法,即便如此,面对各种不同的编程语言,还有千姿百态的软件系统,我们很难有高效快速的通用方法。

但是, 有一些debug时的关注点,可以看作雕虫小技。

1.环境检查

复现一个Bug,一般从环境检查开始。从底层到应用层逐层检查,要耐心确认。同时,关注帮助文档、手册或数据表,关注工作目录或者运行环境的路径。

2. 日志检查

不要害怕被大量的调试日志,看起来很吓人,但实际上是来帮忙的。大多数时候它会告诉我们真正的问题是什么和在哪里!在25年前,debug C 语言程序的时候,自己好像只能依赖printf来定位问题。

根据日志思考:什么导致了这个错误?错误是如何触发的?...

3. 代码核查

先看看拼写错误吧,typo 或者简单的语法疏忽有时不易发现。有时候括弧或者大括弧的幸运碰撞,有时候context成了content,fetch成了fecth,如果对自己的代码熟视无睹,可以让别人帮着看一眼。

同样,“以终为始”,先检查是否接收了正确的数据类型,一般的防御式编程都可以看到接收的参数或数据。如果接收方合乎预期,跟随调用链的脚步,看调用者的函数,一步一步逼近bug的所在地。

如果定位到了函数,尤其是那些执行的迭代方法(尤其如for、while、do等循环处理),尝试在console上显示一步一步地执行结果。

4. 定向验证

对指定的函数或者逻辑输入固定的数据,或者执行固定的代码来做定向验证,可以是正向的,也可以是逆向的。

如果增加了大量输入还看不到所需输出的话,需要确认一下这些代码真的在执行吗?虽然有了条件语句(如if,switch等),但实际上执行的是在这里么?在条件语句中注入简单的代码,比如打印一个简单的“hello world”,可以帮助您看到程序执行的流程。

当然了,如果有完整一点的单元测试,往往方便的多。

5. 注释代码

如果对于bug发生的逻辑模块位置迟迟不能定位,往往还要回归到通过二分法定位。逐行注释代码的方法可能是可行的,但不是最有效的方法。如果对问题所在没有什么想法的话,这可能是一条必经之路。

6. 手画流程

“好脑子不让烂笔头”,有时候,我们需要一支笔和一张纸,就可以从所有的技术细节中解放出来,就能从视觉上看到事情是如何运作的,把逻辑流程画出来能够帮助我们梳理和定位代码逻辑上的问题。这有点儿像反向工程,尤其对于那些不熟悉的代码,阅读代码并画出流程会提供较大的帮助。

随笔结语

“Zero Bug” 可能是程序员追求的目标,但现实中存在着较大的困难。程序员的日常离不开debug,宽泛一点说是trouble shooting(故障排除)。故障排除在很多时候依赖于经验,反复实践几乎是不二法门,但是,我们可以通过归纳总结自己的经验形成一个“心智模型”,可能是树状的,也可能是金字塔结构,也就是所谓的“套路”。

另外,向经验丰富的程序员学习“套路”也不失为一个有效的途径。最近,我的几个朋友出了一本关于“程序员套路“的书——

(点击封面了解详情)

▌《程序员的三门课:技术精进、架构修炼、管理探秘》

于君泽  李伟山  张洪亮  彭首長  刘朋 著

我们都有一个共同的梦想——成为更棒的程序员,但是如何做?如何学习和精进自己的技术?如何做业务分析和架构设计?如何做技术管理?本书就广大程序员都很关注的问题提供一些思路和方法。

快到”1024程序员节“了,作为福利,本文获得点赞最多的3名读者将获赠此书,活动截止时间10月24日。

希望各位有所得!

考资料:

  • https://www.techug.com/post/cutting-edge-debugging.html

  • 吉冈弘隆、大和一洋、大岩尚宏,《Debug Hacks中文版:深入调试的技术和工具》,电子工业出版社,2011

  • 张燕飞, 张春熙, 李宇明, et al. DBugHelper:分布式系统Debug协助工具[J]. 华东师范大学学报:自然科学版, 2016(5):153-164.

关联阅读:

无我编程的10条诫律

关于软件开发,都应该知道的10个常识

软件架构的10个常见模式

我的CSDN博客10年

嵌入式开源软件的10大弊端

coding之外的3个日常:开会、提问和读书

如何进入一个新领域

一个函数的自白

计算机网络的元认知、实践与未来

智能音箱场景下的性能优化

全栈的技术栈设想

再谈<全栈架构师> 一文

面向全栈的技术管理

1024程序员节前夕,Bug与Debug的随笔相关推荐

  1. 别样的1024程序员节“无Bug市集”

    刚刚过去的1024程序员节 让程序员们嗨了一把, 最嗨的,莫过于网红地后厂村了 传智播客举办的"无BUG市集", 10月23日在西二旗大飞盘下,趣味开市! 25家企业,6大互动区, ...

  2. 2022年1024程序员节随笔

    目录 0. 缘起 1. 程序员 1.1 成长 1.2 月亮与六便士 1.3 坚定和怀疑 1.4 归田园居 1.5 真的猛士 2. 梦想 2.1 信仰 2.2 务实 2.3 期待 3.总结 0. 缘起 ...

  3. 1024程序员节,你是我们要找的那条锦鲤吗?

    参加2018 AI开发者大会,请扫描海报二维码 叮咚,您有一封 #1024吐槽狂欢派对# 邀请函请查收. ▌什么是程序员? 全员格子.黑框眼镜,还是等于创造力+忍耐力? 刻板标签.思维定式,还是高阶自 ...

  4. 1024程序员节 | 我在腾讯自研数据库,我为技术代言

    随着互联网的发展,"程序员"这个名字逐渐为人们所关注到,其所代表的标签印象也变得更加多样 -- 改变世界?Debug专业户?格子衫代言人?--事实上,有那么一群人,比如腾讯数据库工 ...

  5. 1024程序员节,向改变世界的程序员致敬

    前个言 正值1024程序员节日来临之际,今天心血来潮,想写篇文章来为我们这些猿猿致敬,也算了却一个心愿,让我们这些猿猿们以自己从事的职业为豪为荣. 可能我们的着装遭人吐槽,可能我们的玩笑经常别人听不出 ...

  6. 1024程序员节:北京尚学堂向改变世界的程序员致敬

    2019独角兽企业重金招聘Python工程师标准>>> 写在前面 正值1024程序员节日来临之际,今天心血来潮,想写篇文章来为我们这些猿猿致敬,也算了却一个心愿,让我们这些猿猿们以自 ...

  7. 你们知道 “1024 程序员节” 该怎么过吗?虎牙带你了解一下程序员!

    写在前面 为什么10月24日是程序员节? 因为程序员热爱1024呗! 所以,无论程序员愿不愿意,10月24日都是你们的节日,再次祝你们节日快乐哈! 有的朋友可能对程序员职业不太了解,请准许简要介绍一下 ...

  8. 1024 程序员节 | 请对身边的程序猿好一点

    程序员节起源 程序员的工作我们都知道,编程嘛.但为什么程序员节要在1024呢?1024最早火起来是因为一个"不可描述"的论坛,那里的回帖机制是:新用户发过贴之后,过1024秒才能发 ...

  9. MySQL之父等国际数据库掌门人齐聚,1024 程序员节全体大会重磅官宣!

    10月23-24日,由CSDN.长沙市政府及多家机构联合主办的第二届"长沙·中国1024程序员节"(1024.csdn.net)将盛大举行.今年程序员节活动囊括:岳麓书院尖峰对话, ...

最新文章

  1. ASP.NET Core 基础教程 - ASP.NET Core 基础教程 - 简单教程,简单编程
  2. 西湖大学最年轻博导来了丨93年出生的他,想创造属于中国的“追光”纪录
  3. cmd设置mysql初始密码_windows下mysql初始密码设置
  4. Java 跌落神坛,Python 继续夺冠....凭啥?
  5. 阿里云云计算 25 SLB的原理
  6. Set集合练习题02
  7. 博士申请 | 美国佐治亚理工学院陶默雷教授招收机器学习方向全奖博士生
  8. 苹果手机测距离_苹果没说谎:iPhone和火星车都在用激光雷达
  9. apicloud 使用教程
  10. ubuntu如何安装Mac OS X主题
  11. Mac安装软件时提示“文件已损坏,您应该将它移到废纸篓”解决办法(亲测有效)
  12. php 实现无限极分类详解
  13. 【数据库 Mysql查询系列】--检索出stu表中‘计算机工程’或‘软件工程’专业的学生的记录,结果集按学号升序排序。
  14. 数据库系统概念 | 第三章:SQL介绍
  15. 成都首秀,体验身边的AI——2019京东人工智能大会
  16. CRM后台管理系统:HTML+CSS+JavaScript制作企业网站后台管理系统模板网站(46个页面)...
  17. 360网盘440.5G免费送
  18. 硬核卖家天天骂顾客,美团还给评了一个“人气店铺”。
  19. 工程图学及计算机绘图第二版答案,工程图学及计算机绘图习题集 第3版
  20. Web image标签 有些JPG格式照片不能显示问题 解释及解决

热门文章

  1. 超详细的编码实战,让你的springboot应用识别图片中的行人、汽车、狗子、喵星人(JavaCV+YOLO4)
  2. java实现文件管理
  3. 转(havel 算法)
  4. xampp 403 禁止访问 问题解决
  5. python时间戳是什么意思_python时间戳是什么
  6. 使用Google时区API显示任何城市的实时本地时间
  7. PyTorch强化:01.PyTorch 数据加载和处理
  8. ubuntu18.04中基于Docker搭建tensorflow-gpu开发环境
  9. 服务器系统做成iso镜像,把服务器做成镜像
  10. 肖维勒准则matlab_莱因达 ( PauTa)准则、格拉布斯 ( Grubbs)准则、肖维纳 (Chauvenet)准则 三者的区别...