Bug 和 Debug

它在我的机器上可以很好运行! --程序员谎言之一

什么是程序 Bug

先看看有史以来的第一个 Bug

first bug

人类发现的第一个 Bug 是一只虫子,详细的故事可以去这里查看 格蕾丝·赫柏

现在的程序 Bug 基本不会是虫子,指的的程序的缺陷或者漏洞,这些缺陷或漏洞使得程序没有达到预期的结果,比如 Web 界面错位,软件突然崩溃等等异常情况。

什么是 Debug

程序有 Bug,就需要找到 Bug 并且修复,这个过程就叫做 Debug。

如何 Debug

任何一种编程语言都有一种排查 Bug 的基本方法:单步调试

单步调试指的一步一步跟着程序去运行,观察程序的变量值,然后定位产生 Bug 的原因。

单步调试过程

  1. 设置程序断点(breakpoint)
  2. 程序运行到断点后进行单步调试,跟踪变量。

Python 如何进行单步调试

Python 的单步调试工具是 pdb(Python Debugger),Python 内置的一个模块。

设置断点的方法 import pdb; pdb.set_trace()

调试命令:

  • l list 查看当前将要运行的代码
  • p print 打印查看变量
  • pp pprint 格式化打印查看变量
  • n next 运行到下一行代码
  • s step 同 next 运行到下一行代码,如果遇到函数会进入到函数中,next 不会进入到函数中
  • c continue 程序继续运行
  • r return 如果调试过程进入到了一个函数中,会让函数立即返回结果

Python 的 pdb 相当于打开了一个 Python 的 shell,所以 Python shell 能干什么,pdb 就能干什么。

Python 有 ipython 这个 shell,当然也有功能更丰富的 ipdb 模块,使用方法和 pdb 一样。

下面我就用 pdb 来调试 Caculator 函数,让大家理解 pdb 的工作原理。

  • 设置断点

breakpoint

  • 调试命令的使用

command

重要提示:调试完了记得删除断点。

通过上面两个图大家对单步调试应该有个直观的理解,如果还理解不了,就动手试试吧

其他调试方法

除了单步调试,我们还可以使用 print 打印变量来进行调试,这种办法也有一定的场景,比如你已经很确定 Bug 是出现在代码的什么位置使用 print 可以立马验证,如果你不确定 Bug 在哪还是单步调试效率要高一些。

调试思想

Rob Pike 关于调试的故事 http://blog.jobbole.com/25564/

在我加入贝尔实验室一年多后,我开始和Ken Thompson一起在开发一个针对由Gerard Holzmann设计的很小的
图形化交换语言的即时编译器上做结对编程。我打字比较快,所以我坐在电脑前,Ken站在我身后看我编程。
我们开发的很快,但经常会遇到问题,而且可以看出来出错了——毕竟这是一个图形化的编程语言。当程序出
错时,我本能的一头扎进问题,检查报错跟踪信息,添加调试打印语句,启动调试器,等等,但Ken只是站
在那思考,完全不理会我也不查看我们写的出问题的代码。一段时间后我发现一个规律,Ken经常会比我先找
到问题出在什么地方,而且会突然的喊一嗓子,“我知道什么地方的问题了。”每次他的判断都很准确。我认识
到,Ken已经在脑海里构建了代码的模型,当有问题出现时,那是他脑子里的模型出了问题。在思考为什么会
发生这些错误时,他能凭直觉找到模型中什么地方不对或发现写的代码跟这个模式什么地方有出入。

Ken教会了我一个极其重要的习惯:纠错前先思考。如果你一头扎进问题中,你可能只解决了当前出现问题的
代码,但如果你先思考这个错误,这个bug是怎么引入的?你通常发现和纠正一个更高层次的问题,进而改进
了系统设计,防止了更多bug的出现。

我认识到这种编程思考模式非常的重要。有些人痴迷于一行行的、使用各种工具来调试所有的东西。但我现在
相信,思考——不看代码的思考——是最好的调试途径,因为它能让你开发出更好的软件。

调试的时候应该先思考为什么会出现 Bug,不要立马陷入代码细节中,当你思考清楚后你会发现修复 Bug 也是小菜一碟。

总结:

这一节学习了 Bug 的概念和单步调试方法,介绍了定位 Bug 的思想,解决 Bug 最难的地方在于定位 Bug 产生的原因,进行 Bug 调试前的思考才是最重要的,单步调试只是验证我们想法的工具而已。

results matching ""

    No results matching ""