这是高软的第二次作业,主要就是编程实战,这次确实学到了东西,以前只是直到回调函数,但是不知道回调函数是干嘛用的。
一、实验要求
在VSCode下编译运行代码
通过VSCode+GDB调试程序找出quit命令无法运行的bug产生的原因
分析callback接口的运行机制,总结callback接口设计的方法
二、实验过程
1、在VSCode下编译运行lab5-1.tar.gz
2、找quit函数无法执行的bug
gcc -g linktable.c menu.c -o menu 输入'quit'指令,发现执行quit命令无法退出程序
可以看出是因为p的指针为空
继续查看
继续查看
通过gbd调试发现,代码的实际操作和分析的是完全一样的。
首先打上断点,然后r程序
一步步调试
最后发现这个函数返回null,定位了bug
查看代码,发现linktable.c中的SearchLinkTableNode函数存在问题如下所示:
/* * Search a LinkTableNode from LinkTable * int Conditon(tLinkTableNode * pNode); * 此处使用了回调函数 */ tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode)) { if(pLinkTable == NULL || Conditon == NULL) { return NULL; } tLinkTableNode * pNode = pLinkTable->pHead; while(pNode != pLinkTable->pTail)//在找到链表最后一个节点时即退出循环,最后一个节点还在啊 { //在模块内部调用外面的方法 if(Conditon(pNode) == SUCCESS) { return pNode; } pNode = pNode->pNext; } return NULL; }
分析如下:while循环条件while(pNode != pLinkTable -> pTail)使得函数在找到链表最后一个节点时即退出循环,因此无法访问最后一个节点,而退出的话需要找到最后的节点,所以我们可以将错误代码while(pNode != pLinkTable -> pTail)改为while(pNode != NULL)来解决bug
修改后的运行结果如下:
说明成功解决了bug。
3、分析callback接口的运行机制
查看老师给的代码:
3.1 回调函数是把函数的指针作为参数传递给另一个函数,callback函数的调用实质上是在一个模块内部调用模块外部的另一个模块实现的函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
3.2 回调函数可以允许用户把需要调用的函数的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。
3.3 callback函数的使用提高了代码的重用性,实现了更松的耦合。同时将一些内部结构接口隐藏,简化了用户接口,更保证了使用安全,减少误操作。