Archive for 八月 2013

自己动手实现Lua调试器

这段时间在qnode项目中新增了一个叫ldb的子项目,它的作用是使用C语言实现了一个lua调试器,后面将会在qnode中嵌入对调试lua脚本的支持。

先来简单提一下ldb的用法,在ldb目录的子目录test中,有一个main.c文件,其中使用ldb库提供的API实现对lua脚本的调试演示:

#include 
#include "ldb.h"

ldb_t *ldb;

static int
c_break(lua_State *state) {
 

关于调试的一些想法

这几天一直忙于跟同事联调测试,其中有一些关于这些的思考,整理一下记录在这里吧。

先从最简单的说起,如何调试和分析问题?这里不涉及具体的应用场景,也不讲工具比如gdb,printf打日志的使用,仅谈方法。我想最能描述如何分析查找问题的思路应该是二分法:遇到了问题A,那么首先将这个问题依次分解为几个小问题a,b,c等,然后再把这些问题再次的分解,直到不能再分解为止。然后开始针对最小的问题开始逐步定位。逐步定位时又有技巧,如果问题A由几个可能会变化的环境影响,那么要想办法在某次查找时只留下一个变量,这样可以确保被影响的因素少,否则出问题的时候你不能确定到底是哪里出了问题。就按照这样的思路,一层一层将问题的封装层剥离开,直到还原到问题的本质。

这个方法的思路,其实反过来可以算是写代码的思路。你写一个功能,首先也要将它分解成几个小功能,每个小功能写完了,也要有针对性的测试用例保证它们根据某些输入可以有相应的输出。

OK,前面提到了分析和查找问题的思路。看上去是很简单的,但是很多时候仅知道方法还是不够的。

我这两天遇到的一个在联调时出现的问题就是,出现问题的时候,对方同学总是认为自己是没有错误的,而他给我提供的他认为正确的证据在我看来又是不那么站得住脚的,于是最后发现确实是他的问题。

比如某个检验值,需要的是使用两个数据根据一个算法产生,然后C端生成之后发给S端,由S端再根据这个校验值将数据还原回来。我做为S端的,拿到这个数据之后发现不能还原,于是大家对了一个生成这个值的时候调用函数时的一些flag是不是一样的,发现都是一样的之后还是没发现问题。于是C端这位同学就认为是这个算法库出了问题。

到这一步,我也不能确定是哪里的问题。但是根据上面的讲过的思路,我希望做的是,将这个问题还原到最简单情况,于是我写了一个单独的,除了这个库之外不依赖其他库的简单程序,它做的事情很简单:从文件读入数据,然后再使用那个算法生成校验值。发现我自己生成的数据,是可以正常还原回来的。于是我要求C端的同学也要这样将这个问题最简化,在C端也仅使用最简单的读文件,然后还原看看行不行。

这个时候问题就来了,C端的同学很不情愿–他的理由仍然是:我的代码是没有问题的,这么做是没有意义的。于是软磨硬泡,将我的理由说给他,告诉他我希望能有这样一个最简化的环境来测试这个算法库是不是对的。甚至为了节省他的时间,我把我的测试代码给他,因为这本身就是很简单的代码嘛,只是看你想不想写罢了,与其讨论有没有意义这些扯皮的问题,不如老老实实的查证问题。最后他终于发现是自己使用的字符串类,在读取数据的时候出了问题,导致了生成的校验值失败。

这个过程,我体会到的是几点: