一、实验要求
-
在VSCode下编译运行lab5-1.tar.gz
-
通过VSCode+GDB调试程序找出quit命令无法运行的bug产生的原因
- 分析callback接口的运行机制,总结callback接口设计的方法
二、实验过程
1.安装minGW。
建议使用离线版,需要注意的是要手动配置环境变量,可参考这个文章:https://www.jianshu.com/p/d66c2f2e3537
接下来在vscode上进行操作,发现各种编译错误,所以改用ubuntu进行实验:
发现错误,经过群友提醒,加上include
我们先进入menu.c进行查看,看看哪里输出了“this is a wrong cmd!”
显而易见,原因是p==null。
p指针又是由FindCmd这个函数返回的,我们要检查它。
看来需要继续调查SearchLinkTableNode函数,不过在menu.c中没有。在linktable.c文件中找到SearchLinkTableNode函数,我们来继续检查:
分析了以上代码可以发现,输入quit命名返回错误信息是因为SearchLinkTableNode函数返回了NULL指针,很明显返回NULL指针只有在pLinkTable和Conditon至少有一个为NULL或者直到pNode循环遍历结束以后也未满足Conditon(pNode) == SUCCESS的条件,很显然前者我们可以排除,我们来分析后者的情况。
我们来看看LinkTable的数据结构是什么:
通过分析以上的代码,我们很容易发现,当pNode遍历到最后一个指针时候,并未判断Conditon(pNode) == SUCCESS是否成了,
而是直接返回了NULL指针,因此将while循环的条件改为pNode!=NULL:
成功!
三.分析callback接口的运行机制,总结callback接口设计的方法
编程分为两类:系统编程(system programming)和应用编程(application programming)。所谓系统编程,简单来说,就是编写库;而应用编程就是利用写好的各种库来编写具某种功用的程序,也就是应用。系统程序员会给自己写的库留下一些接口,即API(application programming interface,应用编程接口),以供应用程序员使用。所以在抽象层的图示里,库位于应用的底下。
当程序跑起来时,一般情况下,应用程序(application program)会时常通过API调用库里所预先备好的函数。但是有些库函数(library function)却要求应用先传给它一个函数,好在合适的时候调用,以完成目标任务。这个被传入的、后又被调用的函数就称为回调函数(callback function)。
打个比方,有一家旅馆提供叫醒服务,但是要求旅客自己决定叫醒的方法。可以是打客房电话,也可以是派服务员去敲门,睡得死怕耽误事的,还可以要求往自己头上浇盆水。这里,“叫醒”这个行为是旅馆提供的,相当于库函数,但是叫醒的方式是由旅客决定并告诉旅馆的,也就是回调函数。而旅客告诉旅馆怎么叫醒自己的动作,也就是把回调函数传入库函数的动作,称为登记回调函数(to register a callback function)。
回调函数至少要有三种函数:
-
主函数:相当于整个程序的引擎,调度各个函数按序执行
-
回调函数:一个独立的功能函数,如写文件函数
-
中间函数:一个介于主函数和回调函数之间的函数,登记回调函数,通知主函数,起到一个桥梁的作用
在该实验中int Conditon(tLinkTableNode * pNode)函数是一个回调函数。