运行环境:macOS Catalina10.15.1 + VSCode1.42.1
一. 在VSCode下编译运行lab5-1.tar.gz 即http://pan.baidu.com/s/1pJ0qAIv
1. 使用gcc编译源代码,可执行文件命名为menu,编译器报出warning
2. 根据提示在menu.c中引入头文件 include
3. 运行menu,发现help、version命令正常,quit命令却提示“This is a wrong cmd!”
二. 通过VSCode+GDB调试程序找出quit命令无法运行的bug产生的原因
1. 安装插件CodeLLDB,解决macos10.15下调试进程无法打断点的问题(断点处不停),参考 https://blog.csdn.net/mgsky1/article/details/103825710?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task。由于网速问题,可在github上手动下载codelldb-x86_64-darwin.vsix之后,通过快捷键Command+Shift+P,Extensions: Install from VSIX进行安装
2. 在menu.c中找到“This is a wrong cmd!”所在位置(line 111),可以看到它的判断条件是p==NULL, 而p的值又来自于line 108行的FindCmd函数,初步判定错误出在此函数
3. 找到FindCmd函数,发现它只有一行,即调用了SearchLinkTableNode函数,再次判定错误出在此函数的返回值
4. 找到SearchLinkTableNode函数,它在linktable.c里,并在三个return的位置打上断点
5. 分别在控制台输入 help、version 和 quit,发现输入前两个时,SearchLinkTableNode函数在line 153处返回,返回值为当前结点,而输入quit时函数在line157行返回NULL
6. 去掉line 146 和 line157行的断点,在line 149、line 151处打上新的断点,重新输入 quit 进行调试;发现在第三轮while循环时,由于pNode == ppLinkTable->pTail,本该在循环中被判断的pNode跳出循环,函数在line157返回了NULL。我们猜测可能是因为“quit”结点是pLinkTable的最后一个结点pTail,所以不止是它,只要是pLinkTable的最后一个结点就永远无法被正确执行。
7. 查看pLinkTable的定义,在main函数line 102,调用InitMenuData函数初始化ppLinktable时,链表ppLinktable第一个结点为“help”,第二个结点为“version”,第三个也就是最后一个结点为“quit”;印证了之前的猜测。
8. 我们把“version”和“quit”调换位置重新编译运行,即在上图中 1 2 3 -> 1 3 2, 发现如之前所料,help命令和quit命令正常,version命令报错;所以quit命令本身并没有任何问题,出现bug的原因仅因为while循环的退出条件有误。
9. 修改while循环的退出条件为 pNode != NULL 即可解决这个bug
三. 分析callback接口的运行机制,总结callback接口设计的方法
1. 什么是回调函数(callback), call vs callback?
call是直接调用,我调用系统函数,就是直调;
callback是回调,我调用系统函数A,系统函数A又需要传入我的函数B作为参数,这种情况下,我并没有直接调用函数B,但是函数B还是被执行了,函数A调用函数B就是回调。
A "callback" is any function that is called by another function which takes the first function as a parameter.
简单来讲,回调函数是一个特殊的函数,它的名字(即指向函数地址的指针)作为参数被另一个函数调用。
2. 一个生动的例子(来自知乎https://www.zhihu.com/question/19801131/answer/13005983)