如何调试程序

Posted by 阿呆 on 2019-01-18

写在前面

这事是不能拖的,我发现,对于代码调试的一知半解,在很大程度上影响到了我的开发效率。所谓工欲善其事必先利其器,综合网上很多的资源,以及自己的一些思考,有了这样一篇blog.由于自身水平有限,会不定期地更新一些程序调试的经验和心得。

什么是代码调试

代码调试指的是通过日志或者IDE来找出程序的错误,从而使代码达到预期效果的一种手段。

调式的难度和程序的类型有直接关系,比如并发或者并行程序的调试难度会大很多,因为你根本无法判断程序的执行流程,但是无论是怎么样的代码结构,都有些共同的调试手段,这里,我们先来讲讲log和IDE的debug模式

Log打印

对于Android来说,SDK内置了log函数,可以分级打印不同的信息,不过我建议自己封装一个log,简化log的写法

对于日志来说,选择那些程序的关键节点和关键变量,在没有大概地思路地情况下,多打印日志,避免频繁地添加日志信息

Debug模式

这里以Android Studio为例,讲解Debug模式下如何调试Android程序

左边红色的为设置的断点,单机断点则可以取消断点,右击则可以设置断点条件,也就是满足什么条件程序会在此处被中断,比如我们设置 selector = 5 ,那么程序第一次中断就发生在第6次循环的时候

点击Debug运行

查看调试面板

以上,我们便进入了调试阶段,下面来分析一下如何使用AS的Debug模式

简单调试

Step Over {一步一步往下走}

从断点开始,每按一次单步调式(或者F8),程序就会往下走一步,注意,不是直接跳到下一个断点,而是一步步往下执行,但是是局限在方法内部,调试信息不会进入链接到的外部方法,这里就不会在stepNext里面记录相关信息

Step Into {进入链接到的外部方法}

在这里,就是这个stepNext方法,请看下图

下面没有截好图,就用代码替换一下

1
2
3
4
5
6
7
8
9
private void stepNext(int i){   // i:5
Log.e(TAG, "stepNext: "+i ); //TAG:MainActivity , i:5
}


Debugger:
stepNext:27,MainActivity
test1:22
onCreate:14

Force Step Into{所有方法看完}

这个是可以看到你所调用的所有方法的实现会让你跟着它走一遍(不局限于你写的函数),研究源码使用非常方便

Step Out {有断点下一个,走完断点继续走}

这里如果我们的一个流程(当前函数)当中(包括调用的方法,将其展开),如果有断点走到下一个断点,如果没有断点,而是在一个调用的方法当中,会跳出这个方法,继续走。

结合下面的例子来会比较好理解

对于上面的第一个断点而言,点击 step out,会跳到这个流程(包括stepNext了)的下一个断点,如果没有,则跳出for循环所在的函数。这里,在其调用的方法 stepNext 中存在下一个断点,则进入到这个断点。

那么在第二个断点处点击 step Out 呢,我们看到,在 stepNext方法中,不存在下一个断点了,所以跳出它,到跳出它执行到的地方,这里就是第30行的Logger语句辣!

Run To Cursor {直接跳动到光标所在处}

很快执行到光标所在的位置,而不需要打断点,需要注意的是,如果在跳转流程中,存在断点,会先到断点,再次直到跳完中间的断点,才会到达光标处

视图图标:一个斜向下的箭头 + 一个 Cursor(光标图案)

高级调试

一些更便捷的使用方式

跨断点调试

如果我们设置了多个断点,现在我们需要直接跳转到下一个断点,那么直接点击下图就可以了

观察变量{TODO}