源地址: http://blog.csdn.net/kaparo/article/details/5887876

调试可以深入程序内部,观察运行时各个变量的值。但是,并不是一出现bug就要调试。调试最适合用来探究一些自己不太熟悉的语言特性或者是技术。比如你对C++某些语句的作用不太熟悉,对某个库函数的作用不太熟悉,调试一下,就可以看得清清楚楚了。如果程序只是逻辑出错误,最好的方法是测试,通过逐个单元的测试,找出问题的所在。为什么测试的效率更高?因为测试可以是自动化的,你可以编写测试代码,一次性地完成很多测试,但调试只能一步一步地来。调试的好处是可以直接看变量的值,而测试的话,必须写额外的代码把变量的值输出到控制台或者日志文件里。下面说一些调试的技巧。

    断点

最简单的一种,设置一个断点,程序执行到那一句就自动中断进入调试状态。

    单步执行

有三种,一种是每次执行一行;一种是每次执行一行,但遇到函数调用就会跳到被调用的函数里;一种是直接执行当前函数里剩下的指令,返回上一级函数。在Visual Studio中,上面三种方法对应的快捷键分别为F10、F11、Shift+F11。

    监视

调试器可能会自动列出一些相关变量的值,但是你可能还关心其它变量的值,可以添加对这些变量的监视。还可以监视一个表达式的值,比如a+b。但是,这个表达式最好不要修改变量的值,比如监视a++都会导致监视时修改了a的值,影响了程序的运行结果。

    条件中断

假如你有这样的循环:

for(int i=0;i<100;i++){

for(int j=0;j<100;j++){

……

}

}

你怀疑当i=10且j=10的时候执行有问题,那如何调试?用断点的话,从i=0的初始状态,需要中断10次才能到i=10,然后从j=0也需要再中断10次,才能到j=10的状态。所以想进入i=10且j=10的状态,需要中断20次,这太麻烦了。可以使用条件中断:

for(int i=0;i<100;i++){

for(int j=0;j<100;j++){

if(i==10 && j==10){

; //空语句

}

……

}

}

在空语句的那一行设置断点就可以了。

上面的if结构太占地方,还可以用assert:

assert(i!=10 || j!=10);

断言i不为10或j不为10,那么当i=10且j=10的时候,断言就不成立,程序就会中断,进入调试状态。

有时候用throw也可以中断:

if(i==10 && j==10)throw;

但是最好不要这样做,调试器不一定会在throw的地方中断。

    控制变量法

其实这已经不算是调试的内容了,但是也是一种找出bug原因的手段,所以还是在这里说。

控制变量法常用于科学研究中,比如说,研究牛顿第二定律a=F/m,a与F和m都有关,那么可以先固定m,研究a与F的关系;然后固定F,研究m与a的关系。

对于一个程序来说,一个bug可能跟多处代码有关。假如你怀疑这个bug与某些语句有关,可以把这些语句注释掉,或者是改一改,看看bug是否还存在,如果不存在,说明确实跟这些语句有关。(当然,要保证程序少了这些语句之后还可以顺利运行。)如果bug还存在,就说明它跟这些语句无关。

有些时候我们缺乏调试工具,比如在网页上运行的程序,在特殊设备上运行的程序,那么控制变量法是一种很有用的代替手段。

    二分法

二分法是控制变量法的进一步扩展。

在数学上,二分法用于求一个连续函数的根。比如一个函数f(x),如果f(x1)>0且f(x2)<0,那么在区间x1和x2之间,必定存在一个x,使f(x)=0。然后我们再考察区间的中点x3=(x1+x2)/2,如果f(x3)>0,则函数的根就在区间x3和x2之间,如果f(x3)<0,那么函数的根就在区间x1和x3之间。如此不断地把区间一分为二,最后锁定函数的根。

对于一个程序来说,如果当前情况是有bug的,那就好比是f(x1)>0;如果你把main函数里所有的操作都注释掉,那么程序什么都不做,就不可能有bug,那就好比是f(x2)<0;于是在这两种状态之中,肯定存在一些临界的语句,当这些语句改动的时候,就会使程序在有bug和无bug状态间切换,这些语句就是bug的原因所在。运用二分法的思想可以锁定这些临界语句。一开始先对程序做一些大刀阔斧的改动,比如说,程序的主循环会循环10次,就改成1次;程序有10个功能,就关掉5个功能。看看哪些改动,可以让程序由有bug状态切换到无bug状态。找到这样改动后,就把这个改动再细分成几个小改动,比如关掉5个功能,就细分为关掉一两个功能,再看看哪些小改动可以让程序由有bug状态切换到无bug状态。如此一步一步缩小包围圈,就后锁定一个无法再分的小改动,这个改动就是bug的原因所在。

    同步法

有些bug是由于多线程而产生的。因为在不同线程里的操作我们无法预测其发生的顺序,可能当它们按某种次序进行时,bug不会出现,当它们按另一种次序进行时,bug就出现了。比如多线程那一节说到的那个银行帐户,如果没有加同步锁,就会出现这种bug。对这种bug的调试是很困难的,有时你运行程序发现了bug,而在进行调试的时候,由于执行顺序不同了,bug又不出现了。

为了解决这个问题,我想了一个办法,就是利用同步事件,强行把多线程的程序按照预定好的顺序去执行。比如说有两个线程,一开始就让线程1运行,线程2睡觉,线程1运行到某个特定的点后,就换线程2运行,线程1睡觉。任何时候,都只有一个线程可以运行。我们可以在多次运行的过程中使用不同的执行顺序,如果按某种执行顺序运行之后bug浮现了,那么就把这种顺序记录下来。然后按照这种顺序进入调试,找出bug。

用这种方法一定要谨慎,如果你的程序里本来就有线程同步的代码,再加上这些强制的同步,可以会导致死锁。

《高效编程十八式》(11/13)调试 王伟冰相关推荐

  1. 《高效编程十八式》后记

    后记 王伟冰 首先,我为什么要写<高效编程十八式>.其实就是想把自己编程过程中学到的.领悟到的东西整理整理,发出来大家讨论讨论.我不是计算机专业的学生,我喜欢编程,但是在我所在的学院里像我 ...

  2. 《高效编程十八式》目录

    本文讨论的是如何提高编程的质量和效率,涉及编程的十八个方面:类,函数,泛型,委托,封装,约束,继承,多态,宏思想,语法糖,命名,陷阱,异常,性能优化,多线程,代码编辑,测试,调试.     示例代码主 ...

  3. 正则十八式-第一式:直捣黄龙

    少年,见你骨骼精奇,是百年一遇的练武奇才,你我又是有缘人,随为师修炼吧 正则十八式-第一式:直捣黄龙 正则十八式-第二式:控鹤擒龙 正则十八式-第三式:龙跃于渊 正则十八式-第四式 挫骨扬灰 藏扇仙: ...

  4. 思维导图的三招十八式

    思维导图的三招十八式  张鄂勇 编著 ISBN978-7-121-14010-5 2012年1月出版 定价:49.00元 16开 396页 宣传语:会降龙十八掌,才混得到九袋弟子.         懂 ...

  5. 正则十八式-第四式 挫骨扬灰

    正则十八式-第一式:直捣黄龙 正则十八式-第二式:控鹤擒龙 正则十八式-第三式:龙跃于渊 正则十八式-第四式 挫骨扬灰 Flutter大军来到,Container战将率领字符大军来到,师徒二人渐入绝境 ...

  6. 正则十八式-第二式:控鹤擒龙

    少年,见你骨骼精奇,是百年一遇的练武奇才,你我又是有缘人,随为师修炼吧 正则十八式-第一式:直捣黄龙 正则十八式-第二式:控鹤擒龙 正则十八式-第三式:龙跃于渊 正则十八式-第四式 挫骨扬灰 接上篇: ...

  7. 浙江大学pta答案python第四章_浙大PTA-Python题库 编程题第一章(1-1~1-3)题解

    其他各章题解链接如下 浙大PTA-Python题库 编程题第一章(1-1~1-3)题解 https://blog.csdn.net/zimuzi2019/article/details/1070206 ...

  8. 浙大PTA-Python题库 编程题第一章(1-1~1-3)题解

    其他各章题解链接如下 浙大PTA-Python题库 编程题第一章(1-1~1-3)题解 https://blog.csdn.net/zimuzi2019/article/details/1070206 ...

  9. 《思维导图的三招十八式》读书笔记

    1.书籍信息 --------------------------------------------------------- 书籍名称:思维导图的三招十八式 作者:张鄂勇 出版社:电子工业出版社 ...

最新文章

  1. mysql count(*),count(1)与count(column)区别
  2. 2018 UESTC Training for Data Structures
  3. android gridview拖动排序,Asp.net GridView 拖拽排序    原创(欢迎拍砖,敬请嘴下留情!)...
  4. newifi mini锐捷校园网路由器配置教程
  5. python open gbk_python3 open txt的UnicodeDecodeError: 'gbk' codec问题解决方案
  6. Mysql比较运算符实战
  7. s饥荒服务器物品id,流年饥荒控制台指令大全+物品大全+服务器管理命令大全.docx...
  8. 基于MVC的简易图形编辑器
  9. 客户关系管理系统(CRM)的开发过程中使用到的开发工具总结
  10. Hazelcast Jet Pipeline详解
  11. Vins-Mono系列代码和理论解读<五>.位姿图Pose_graph理论和代码实现细节
  12. 为什么要使用memcache?memcache有什么作用?
  13. 类模板中的友元,友元类
  14. XAMPP之Apache、MySQL不能正常启动的解决办法
  15. CocosCreator报:Maximum call stack size exceeded 的问题
  16. JAVA 数字图像处理----非白即黑的灰,2B青年的自画像
  17. 国内程序员的Linux开发平台-Deepin
  18. 利用VideoView简单实现视频播放 包括 横竖屏切换 声音 亮度 暂停
  19. 中信证券600030
  20. 计算机术语csr是什么,CSR是什么意思 为何CSR越来越重要

热门文章

  1. 绿松和蓝松_美国蓝松——绿松石里的睡美人
  2. 经验分享:新购买移动硬盘格式化为Windows系统和Mac系统同时可以使用的方法
  3. web 打印 样式设置注意问题
  4. slor6.5配置ikanalyzer-solr分析器
  5. 实时渲染入门:(一)概论
  6. 【产品】需求分析与管理
  7. 搭建Exchange 2010
  8. 同一局域网内的数据库的连接
  9. 运营人必懂 | TikTok运营指南
  10. java 拉普拉斯_opencv3_java 图形图像的拉普拉斯平滑Laplacian Laplacian