工程化编程实战callback接口学习笔记
实验要求:
-
在VSCode下编译运行lab5-1.tar.gz 即http://pan.baidu.com/s/1pJ0qAIv
-
通过VSCode+GDB调试程序找出quit命令无法运行的bug产生的原因
- 分析callback接口的运行机制,总结callback接口设计的方法
实验过程:
实验环境:win10, vscode
缺少pthread头文件,参考https://blog.csdn.net/CSDN_WHB/article/details/81475233
输入
gcc -o test menu.c linktable.c -lpthread
得到test.exe文件
输入./test 运行程序,输入help和quit指令
发现quit指令出现错误
检查一下menu源码
int main() { InitMenuData(&head); /* cmd line begins */ while(1) { printf("Input a cmd number > "); scanf("%s", cmd); tDataNode *p = FindCmd(head, cmd); if( p == NULL) { printf("This is a wrong cmd!\n "); continue; } printf("%s - %s\n", p->cmd, p->desc); if(p->handler != NULL) { p->handler(); } } }
可知是p指针为空
查看FimdCmd函数,此函数是通过给定的链表和cmd只返回数据节点的地址
/* find a cmd in the linklist and return the datanode pointer */ tDataNode* FindCmd(tLinkTable * head, char * cmd) { return (tDataNode*)SearchLinkTableNode(head,SearchCondition); }
此函数调用; 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循环表示节点不是表尾则继续循环,但是查看InitMenuData函数发现quit恰好是链表的表尾,故遍历到该节点时没有访问就跳出循环了,此处返回了null
将SearchLinkTableNode函数中while循环的判断条件改为
while(pNode != NULL)
即
重新执行
程序运行成功
callback回调函数
CALLBACK,即回调函数,是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
因为使用此函数可以把调用者与被调用者分开,所以调用者不关心谁是被调用者。它只需知道存在一个具有特定原型和限制条件的被调用函数。简而言之,回调函数就是允许用户把需要调用的函数的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。