gdb 容器可视化概论
背景
为了远程调试,我们需要自己交叉编译 gdb 工具链,这时候你去调试 g++ 的工程,不可避免的就会遇到容器,或者说是 stl, 甚至是 boost;这时候很有可能你看到的就是一堆地址了,毕竟这合情合理,但是这些地址并不是我们关注的地方,我们关心的实际上是容器存储的数据。
现象
这里我直接拿一个现有的工程进行展示,随便找个工程就可以了;其实也就是主要是懒得重新写一个 CMakelists 或者 makefile。 Debug 的工具选择 VScode,如下是我 VScode 的 launch.json。
{
"version": "0.2.0",
"configurations": [{
"name": "使用系统自带 gdb (本地调试)",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceRoot}/bin/web_tc",
"args": ["${workspaceRoot}/bin/config.json"],
"stopAtEntry": true,
"cwd": "${workspaceRoot}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}],
"preLaunchTask": "complie"
},
{
"name": "使用源码编译 gdb (本地调试)",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceRoot}/bin/web_tc",
"args": ["${workspaceRoot}/bin/config.json"],
"stopAtEntry": true,
"cwd": "${workspaceRoot}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}],
"preLaunchTask": "complie",
"miDebuggerPath": "/home/haorui/tools/gdb/bin/gdb",
},
{
"name": "使用源码编译 gdb (远程调试)",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceRoot}/bin/web_tc",
"args": ["${workspaceRoot}/bin/config.json"],
"stopAtEntry": true,
"cwd": "${workspaceRoot}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}],
"preLaunchTask": "complie",
"miDebuggerPath": "/home/haorui/tools/arm-hisiv600-linux-gdb/bin/arm-hisiv600-linux-gdb",
"miDebuggerServerAddress": "172.20.92.88:10002"
}
]
}
launch.json
写的也非常简单,就是用 3 个 gdb 分别调试这个程序,两个运行在宿主机,一个运行在目标机,其中有一个 gdb 是系统自带的,其余两个则是自己手动编译的。
gdb 调试测试
使用系统自带 gdb (本地调试)
使用源码编译 gdb (本地调试)
使用源码编译 gdb (远程调试)
在这里可以正式介绍一下标题的标题 01_gdb容器可视化概论,可视化其实指的是可以不可以直观地查看 STL 容器(当然也不止 stl, boost 也是可以的)。
上面是实机测试的结果,可以看到使用系统自带的 gdb 可以看到容器的内容,而无论是运行在宿主机还是目标机源码编译的 gdb 都没有这个功能,这是一个很有意思的现象,在后面会解释其原因。
分析
网上很多说法说开启 gdb 的 pretty-printer 功能就好了,有两篇博客写的不错,如果你想直接解决问题,你可以参考下:
这里要指出的是, 在VS Code中开启gdb的pretty-printer功能 中写到:
很遗憾虽然pretty-printer是GDB官方提供的,但是并没有默认安装/开启。所以需要手动安装。
需要注意的是,这个脚本是使用python开发的,所以需要7.0及以后的版本的GDB。
这里的说法其实并不恰当,还真不一定需要手动安装,起码 ubuntu 帮你搞定了,在 ubuntu18 亦或是 ubuntu20 上。
pretty-printer
确实要想可视化 stl 容器,一般需要有 pretty-printer 的支持,而这个功能是在 gdb 7.x 之后才加入的;但并不是说上述测试使用的 3 个gdb中,只有系统自带的 gdb 才具备有 pretty-printer 的功能,其实它们都具备这个功能。
从这里你可以看出来,其实三个 gdb 都是具备有 pretty-printer
的功能的,不过你也可以注意下 1 of 1 printers enabled
,这里的 1 是关键,也就是开了跟没开一样。
那么为什么在 VScode 调试时,系统自带的 gdb 又可以看到 容器的内容呢,这是很疑惑的,为此在此将系统自带的 gdb 运行在程序里,使用 VScode 的调试控制窗口,你可以看到:
你可以看到 171 of 171 printers enabled
, 一共开启了 171 个 printer,每个人的系统可能这个数字都不一样,这跟在终端里显示的结果并不一样,是不是很神奇。
展后
后面并不会直接给出解决方案,而是通过 pretty-printer 的原理告诉你如何实现stl容器的可视化,掌握其原理是必要的,例如你以后可能想为你写的结构体也实现类似的功能。