GDB配置(打印STL容器、VS code配置、远程调试debug)
来源:互联网 发布:淘宝用的什么web服务器 编辑:程序博客网 时间:2024/06/07 21:55
- 前言
- gdb定义打印函数
- 配置pretty printer
- gdb gdbserver远程调试
- gdb其他配置
0.前言
Linux开发必须要把gdb玩的666呀,建议先阅读下《C++ vector STL实现详解》。gdb玩的666可以摆脱调试中各种使用std::cout
打印输出变量的恶习,尤其对于大型项目,每次调试都需要增加std::cout
,单单编译时长都能让你发狂,严重影响开发效率。
1.gdb定义打印函数
gdb原生支持定义打印函数,了解类型后,可以自行定制打印函数。目前网上有提供针对stl标准容器的现成文件.gdbinit
,该文件会定义string、vector、map、set、deque、priority_queue
等等,需要可以直接下载这里, 把文件保存为.gdbinit
, 放在用户目录下~/.gdbinit
,每次执行gdb调试会自动加载.gdbinit
初始文件。
文件中vector定义如下
define pvector if $argc == 0 help pvector else set $size = $arg0._M_impl._M_finish - $arg0._M_impl._M_start set $capacity = $arg0._M_impl._M_end_of_storage - $arg0._M_impl._M_start set $size_max = $size - 1 end if $argc == 1 set $i = 0 while $i < $size printf "elem[%u]: ", $i p *($arg0._M_impl._M_start + $i) set $i++ end end if $argc == 2 set $idx = $arg1 if $idx < 0 || $idx > $size_max printf "idx1, idx2 are not in acceptable range: [0..%u].\n", $size_max else printf "elem[%u]: ", $idx p *($arg0._M_impl._M_start + $idx) end end if $argc == 3 set $start_idx = $arg1 set $stop_idx = $arg2 if $start_idx > $stop_idx set $tmp_idx = $start_idx set $start_idx = $stop_idx set $stop_idx = $tmp_idx end if $start_idx < 0 || $stop_idx < 0 || $start_idx > $size_max || $stop_idx > $size_max printf "idx1, idx2 are not in acceptable range: [0..%u].\n", $size_max else set $i = $start_idx while $i <= $stop_idx printf "elem[%u]: ", $i p *($arg0._M_impl._M_start + $i) set $i++ end end end if $argc > 0 printf "Vector size = %u\n", $size printf "Vector capacity = %u\n", $capacity printf "Element " whatis $arg0._M_impl._M_start endend
现在打印vector就很简单了,比如 :pvector v
(vector
变量), 上述定义支持:
pvector v # 打印所有内容pvector v 0 # 打印位置为0的内容pvector v 1 2 # 打印[1, 2]的内容
2.配置pretty printer
上述的配置无法支持unorder map
等C++11新增的容器,除非自己定义新的打印函数,不过也可以通过配置pretty printer来解决,默认安装gcc高版本(>4.6.0)情况下会自带pretty printer
,本文基于gcc-6自带的pretty printer
进行配置,否则可以通过svn来下载最新版本: svn co svn://gcc.gnu.org/svn/gcc/trunk/libstdc++-v3/python
,注意:libstdc++版本要与gcc版本对齐,否则不会正常工作。pretty printer
也支持用户的自定制,具体例子点击此处,实现变量具体打印类,已经gdb类型名字到打印类的映射。下面给出.gdbinit
中pretty printer
配置内容:
.gdbinit增加配置
pythonimport syssys.path.insert(0, '/usr/local/Cellar/gcc/6.4.0/share/gcc-6.4.0/python')from libstdcxx.v6.printers import register_libstdcxx_printersregister_libstdcxx_printers (None)end
其中需要在自己目录下找到libstdcxx
对应的路径,填写在sys.path.insert
变量里,如果不使用pretty printer
, 可以使用/r
参数原生打印。
p /r xxx
注意,在Mac系统中,如果使用gdb版本很高,笔者gdb版本为8.0.1,生成调试程序必须带有-gdwarf-3
参数,只有使用该参数,pretty printer
才能生效,调试信息兼容到高版本。Mac 中高版本gdb调试gcc高版本编译程序,需要编译使用-gdwarf-3。更具体的解释是:gcc版本大于4.8,缺省生成dwarf4版本的调试信息,pretty printer
基于dwarf3
版本,因此gdb中pretty printer
可能无法识别相应类型符号,需要通过选项-gdwarf-3
来生成低版本调试信息,简单编译例子:
g++-6 -g -gdwarf-3 -O0 -o test test.cpp
gdb可以装备VS Code:正常情况下VS Code调试控制台能够直接使用,比如打印map<string, string> cfg_
; 需要在控制台输入:
-exec p cfg_
VS Code调试控制台运行gdb命令都需要加上-exec
,VS Code打印与原生gdb打印一致,如下图所示:
要想在debug过程中,鼠标停靠在变量上,打印变量使用
pretty print
时,需要在debug配置文件launch.json
加入,github官方论坛上解释:VS Code为了追求性能,鼠标停靠变量上、监控区变量时会关闭pretty print
,通过配置launch.json
可以强行打开,配置如下:"setupCommands": [{ "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true}],
笔者launch.json
配置为
{ "version": "0.2.0", "configurations": [ { "name": "gdb", "type": "cppdbg", "request": "launch", "program": "${workspaceRoot}/xgboost", // "args": ["${workspaceRoot}/demo/regression/machine.conf"], "args": ["${workspaceRoot}/demo/binary_classification/mushroom.conf"], "stopAtEntry": false, "cwd": "${workspaceRoot}", "environment": [], "externalConsole": true, "preLaunchTask": "make", // 代码有修改,先执行make编译任务 "setupCommands": [{ // 鼠标悬挂查看变量值,使用pretty print配置 "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true }], // VS Code debug的日志信息,能清楚gdb加载和运行的各种过程,如果没有其他用途可以注释 "logging": { "moduleLoad": false, "trace": true, "engineLogging": true, "exceptions": true // "traceResponse": true }, "MIMode": "gdb" } ]}
效果如下图所示,可见代码变量与监控区的变量显示都是pretty print
形式。
3.gdb + gdbserver远程调试
实际工作中,公司内部库都是基于linux,需要在linux环境下编译程序,经常想快速了解公司内大神们写的模块源码,最好的方式就是debug整个流程。然而对于笔者来说,gdb用的还不是非常6,有时还需要查看文本源码,目前来说调试gdb不太友好,笔者还是喜欢基于IDE的debug调试过程。而公司开发机子系统为Mac,而Mac系统编译不了代码,为了方便debug,需要gdb远程调试功能,也就是说可以支持不同操作系统下的debug。gdb远程调试模式是本地gdb
+远程gdbserver
形式,这种形式也经常用于嵌入式的调试。
首先,安装gdb必须使用--with-all-targets
参数,因为默认安装是基于机子操作系统的结构体系,而远程调试的机子不一定与本机相同,使用该参数主要是适配远程各种平台的结构体系,当然可以下载gdb源码,修改配置中结构体系配置编译安装,这部分读者自行google,同时远程需要安装gdbserver
。
# 本地主机安装gdbbrew install gdb --with-all-targets # 远程主机下安装gdb、gdbserverapt-get install gdbapt-get install gdbserver
远程主机编译程序,运行gdbserver服务监听特定端口:
g++ -g -O0 -o test test.cppgdbserver localhost:9999 test # localhost也可以改成远程主机IP:10.101.8.8# killall gdbserver # kill进程
本地主机执行gdb,在gdb命令行中输入:
target remote 10.101.8.8:9999 # 连接远程symbol-file test # 加入符号文件,可执行文件包含符号文件,test为远程主机编译,通过scp来拷贝到本机continue # 执行调试过程,不是run,因为gdbserver已经启动程序了,后续就可以使用gdb过程。
特殊说明,symbol-file
给定符号文件即可,可以使用objcopy
对可执行文件进行符号文件剥离:
objcopy --only-keep-debug test test.symbol # 对应objcopy --strip-debug test test.bin 只剥离出可执行文件# gdb 程序内加载symbol文件symbol-file test.symbol # 使用符号文件即可
scp文件优化:远程debug需要拷贝远程编译文件或者符号文件,对于大型程序100MB+而言,除非网快,否则需要较长等待时间。优化scp拷贝回来的符号文件大小,符号文件剥离本身是个优化,但对于-O0 -g
生成某大型程序150MB,笔者发现剥离出的符号文件138MB,几乎占据整个可执行文件,约90%。使用-O2
高度优化的是可执行文件大小,符号文件并不减少,而且高度优化会使用分支预测,局部变量优化,函数内联等优化技术而造成代码运行逻辑不一致,尽管运行结果一致,不利于人的debug阅读逻辑。g++
编译生成debug信息是可配置的,-g
后面可以加入level等级,默认是2,level越高信息越全,最低level是1,能减少30%生成的符号文件大小,但是使用该符号文件无法调试,部分变量symbol会被删除。最后笔者只能通过压缩语句来减少文件大小的传输,能优化掉2/3的大小,这样一比较,也没太多必要剥离出符号文件。
tar -jcvf test.tar testscp user@remote_host:xxx/test.tar .tar -jxvf test.tar
VS Code也支持远程gdb调试,需要配置miDebuggerServerAddress
: "miDebuggerServerAddress": "10.101.8.8:9999"
, 同时必须给定可执行文件"program": "${workspaceRoot}/test"
, 但是该文件可以拷贝于远程,而不需要本地编译,这样就可以基于VS Code边调试,边浏览代码,同时可以设置断点。
{ "version": "0.2.0", "configurations": [ { "name":"gdb Launch", "type": "cppdbg", "request": "launch", "program": "${workspaceRoot}/test", "miDebuggerServerAddress": "10.101.8.8:9999", "setupCommands": [{ "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true }, { "text": "set sysroot" //不加载远程so文件,不调试动态链接库,跳过read xxx.so from remote target,能减少每次调试准备时间 } ], "args": [], "stopAtEntry": false, "cwd": "${workspaceRoot}", "environment": [], "externalConsole": true, "MIMode": "gdb" } ]}
4.gdb其他配置
这部分内容会持续更新,笔者会加入gdb实用配置。
1) gdb命令历史保存
set history filename ~/.gdb_historyset history save on
2) 断点保存与恢复
define bsave shell rm -f brestore.txt set logging file brestore.txt set logging on info break set logging off # reformat on-the-fly to a valid gdb command file shell perl -n -e 'print "break $1\n" if /^\d+.+?(\S+)$/g' brestore.txt > brestore.gdbenddefine brestore source brestore.gdbend
每次退出前使用bsave
命令,每次进入gdb想恢复上一次设置的gdb设置断点,可以输入brestore
3) mac系统gdb额外设置
set startup-with-shell off
- GDB配置(打印STL容器、VS code配置、远程调试debug)
- 在eclipse用gdb调试stl容器配置
- VS Code调试配置
- 配置GDB支持STL调试
- GDB调试STL容器
- 配置GDB+GdbServer远程调试环境
- 配置GDB+GdbServer远程调试环境
- 配置eclipse 远程服务器debug调试
- gdb调试-查看STL容器
- GDB调试STL复杂容器
- 使用GDB调试STL容器
- 使用vs code 编辑调试php 配置
- 配置 Code::Blocks 10.05 + gdb 7.1 使支持 STL
- 配置GDB以支持查看stl容器数据
- [ZZ]配置GDB以支持查看stl容器数据
- 配置GDB以支持查看stl容器数据
- 配置GDB以支持查看stl容器数据
- 配置GDB以支持查看stl容器数据
- 在List的add方法添加对象时都是最后的一条记录的重复
- gulp基础使用
- 关于静态绑定与动态绑定的辨别笔记----C++学习之路
- C++学习笔记(二)
- 好书推荐
- GDB配置(打印STL容器、VS code配置、远程调试debug)
- Linux命令与shell脚本
- 【SQL解惑】谜题3:麻醉师谜题
- 语法分析-哈工大编译原理实验二
- 什么是闭包?闭包的工作原理、优缺点、使用场景和对页面的影响
- 子Div使用Float后如何撑开父Div
- centos+nginx+uwsgi+Python3+flask操作步骤
- 购物车
- Postman接口测试工具的使用_1