工程化编程实战callback接口学习笔记

环境

  • 系统:Win10 + ubuntu子系统
  • 版本:16.04
  • gcc版本:7.4.0
  • vscode:1.41.1

任务

  • 编译运行lab5-1
  • 通过VS Code + GDB调试程序找出quit命令无法运行的bug产生的原因
  • 分析Callback接口的运行机制,总结Callback接口设计的方法

编译项目

1.通过gcc编译

工程化编程实战callback接口学习笔记_第1张图片
提示缺少函数声明strcmp,修改menu.c文件内容,加入#include声明,再次编译结果正常

2. 运行项目

工程化编程实战callback接口学习笔记_第2张图片
可以发现quit命令无法正常运行,接下来在WSL中启动vscode来调试。

调试

1. 启动vscode

在wsl中直接运行code即可开启vscode,如图
工程化编程实战callback接口学习笔记_第3张图片
可以看到左下角显示WSL:Ubuntu,此时vscode已连接到wsl环境中。

2. 生成task.json与lauch.json文件

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558 
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "type": "shell",
            "label": "gcc build active file",
            "command": "/usr/bin/gcc",
            "args": [
                "-g",
                "${fileDirname}/linktable.c",
                "${fileDirname}/menu.c",
                "-o",
                "${fileDirname}/link"
            ],
            "options": {
                "cwd": "/usr/bin"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) 启动",
            "type": "cppdbg",
            "request": "launch",
            "program": "link",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "为 gdb 启用整齐打印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        }
    ]
}

3. 调试

现在InitMenuData函数处设置断点,再单步执行观察返回结果。
在InitMenuData的函数定义来看,命令及其执行函数是保存在pNode的节点中的,追入函数AddLInkTableNode内部,可以看出每个命令都是一个链表当中的一个节点,其中pLinkTable中的pHead和pTail分别指向链表第一个元素和链表最后一个元素。
工程化编程实战callback接口学习笔记_第4张图片
移除之前的断点,在main函数中的FindCmd处设置断点,输入“quit”后追入FindCmd函数
工程化编程实战callback接口学习笔记_第5张图片
追踪链表查询函数
工程化编程实战callback接口学习笔记_第6张图片
工程化编程实战callback接口学习笔记_第7张图片
程序利用strcmp函数判断输入命令与链表中保存的命令是否相同。
继续单步执行SearchLinkTableNode的循环,执行两次循环后,pNode指向第三个节点,也就是保存“quit”命令所在的节点时,变量如下图所示
工程化编程实战callback接口学习笔记_第8张图片
此时pNode和pLinkTable->pTail的值相等,不满足while的判断条件,会导致没有对链表的第三块元素检索就终止循环,故无法识别命令“quit”。
要使程序能够正常运行就需要修改SearchLinkTableNode函数中while的判断条件使其能够访问链表中的最后一个元素,简单地修改while循环条件即可。
工程化编程实战callback接口学习笔记_第9张图片
重新编译,结果如下
工程化编程实战callback接口学习笔记_第10张图片

Callback接口

在testlinktable.c可以看到代码中第51-57行分别使用callback调用搜索链表和直接用自定义函数查询链表的示例
工程化编程实战callback接口学习笔记_第11张图片
其函数定义
工程化编程实战callback接口学习笔记_第12张图片
工程化编程实战callback接口学习笔记_第13张图片
callback方法首先调用的是linktable.c中的函数,将自定义的函数SearchCondition的指针通过参数传递的方式提供给中间函数SearchLinkTableNode,而“one by one”则是在一个自定义Search函数体中调用linktable.c中的函数。

callback方法特点是将回调函数以参数的形式将函数指针传递给另一个中间函数,可以提高代码重用度,提高编程的灵活性以及编程效率。

你可能感兴趣的:(工程化编程实战callback接口学习笔记)