在Linux系统下使用GDB调试C++程序【命令行调试与vscode编译器调试】
文章目录
- 1. Linux下编译器,调试器安装
- 2. GDB调试器介绍
- 1. 概述
- 2. 常用调试命令参数
- 3. Linux下C++命令行调试实战
- 0. 安装超级终端Terminator
- 1. 准备代码
- 2. 进入调试模式
- 3. 调试过程
- 4. Linux下vscode使用cmake和gdb:
- 5. 补充:关于vscode的一些标识和快捷键
1. Linux下编译器,调试器安装
sudo apt update
sudo apt install build-essential gdb //安装三个软件
查看安装是否成功
gcc --version
g++ --version
gdb --version
2. GDB调试器介绍
1. 概述
-
GDB(GNU Debugger) 是一个用来调试 C/C++ 程序的功能的调试器,是Linux系统开发C/C++最常用的调试器
-
程序员可以使用GDB来跟踪程序中的错误,从而减少程序员的工作量
-
Linux开发C/C++一定要熟悉GDB
-
VScode是通过调用GDB调试器来实现C/C++调试工作的
,而vscode可以在linux和windows环境下运行
Windows中,常用的集成开发环境,如VS,VC等已经内嵌了相应的调试器
GDB的主要功能:
- 设置断点(断点可以是条件表达式)
- 使程序在指定的代码上暂停执行,便于观察
- 单步执行程序,便于调试
- 查看程序中变量值的变化
- 动态改变程序的执行环境
- 分析崩溃程序产生的core文件
2. 常用调试命令参数
调试开始:执行gdb [exefilename]
,进入gdb调试程序,其中exfilename
为要调试的执行文件名,以下命令后括号内为命令的简化使用,比如 run(r)
,直接输入命令 r
就代表命令 run
help(h) #查看命令帮助,具体命令查询在gdb 中输入help + 命令
run(r) #重新开始运行文件(run-text:加载文本文件,run-bin:加载二进制文件)
start(s) #单步执行,运行程序,停在第一行执行语句
list(l) #查看源代码(list-n从第n行开始查看代码。list+函数名:查看具体函数)
set #设置变量的值
next(n) #单步调试(逐过程,函数直接执行)
step(s) #单步调试(逐语句,跳入自定义函数内部执行)
backtrace(bt) #查看函数的调用栈帧和层级关系
frame(f) #切换函数的栈帧
info(i) #查看函数内部局部变量的数值
finish #结束当前函数,返回到函数调用点
continue(c) #继续执行
print(p) #打印值及地址
quit(q) #退出gdb
break + num(b) #在某行达断点
info + breakpoints #查看当前设置的所有断点
delete + breakpoints num(d) #删除第num个断点
display #跟踪查看具体的变量值
undisplay #取消跟踪观察变量
watch #被设置观察点的变量发生修改时,打印显示
i watch #显示观察点
enable breakpoints #启用断点
disable breakpoints #禁用断点
x #查看内存x/20xw 显示20个单元,16进制,4个字节没单元
run argv[1] argv[2] #调试命令传参
set follow-fork-mode child #Makefile项目管理,选择跟踪父子进程(fork)
- 编译源代码时需要加上
-g
,产生的可执行文件才能用gdb
进行调试,例如:gcc -g main.cpp -o main
- 回车键:重复上一条命令
3. Linux下C++命令行调试实战
0. 安装超级终端Terminator
sudo apt install terminator
具体使用方法可以查看博文:第七章:超级终端Terminator
1. 准备代码
创建一个C++源代码文件 src/04_debug/sum.cpp
,添加以下代码
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
int N = 100;
int sum = 0;
int i = 1;
while(i <= N){
sum = sum + i;
i = i + 1;
}
cout << "sum = " << sum <<endl;
cout << "The program is over " <<endl;
return 0;
}
2. 进入调试模式
在进入调试模式之前,先编译源代码,如下过程。
普通编译方式
g++ sum.cpp -o no_g.out
编译出用于调试的可执行文件
g++ -g sum.cpp -o yes_g.out
使用gdb
命令进行调试,如果我们调试 no_g.out
,将会提示错误。因为no_g.out
这个可执行文件不包含用于调试的信息,输入quit
再按回车即可,通过gdb yes_g.out
指令执行包含调试信息的可执行文件,看到以下输出
此时可以正常进入调试
3. 调试过程
直接执行
run
或者使用简写r
,运行结果如下图
在第11行打断点
break 11
运行结果如下图
也可以使用简写的方式,在第12行打断点
b 12
结果如下图
使用info breakpoints
指令或者指令简写i b
查看当前的断点,如下图结果
使用run
指令或者r
指令执行程序,此时命中了第11行断点,如下图内容
此时可以查看变量的值,如查看i的值,可以使用print i
或者p i
指令,如下图
此时程序执行到第11行处,如果我们需要继续执行,输入continue
指令并按回车即可,程序将执行到代码的第12行,如下图
因为我们是在while
循环体内,i
的值将不断变化,如果我们需要跟踪i
值的变化,需要输入display i
指令即可,再输入continue
指令让程序单步执行,每次都会打印i的值
,如下图
可以观察到,通过循环,又回到了第一个断点,此时i
的值已经变成了2。在gdb调试中,如果我们只按回车键,gdb将执行我们最后一次输入的指令,所以我们可以一直按回车键继续让程序单步执行。
当断点执行都某个位置时,我们想要查看断点附近5行的代码,可以执行list
指令进行查看,如下图
4. Linux下vscode使用cmake和gdb:
-
vscode中安装插件:cmake tools插件,cmake插件。C/C++ 插件
-
书写CMakeLists.txt,编译得到可执行文件:具体步骤查看博文:3.7.1 外部构建方式举例,然后调试通过CMake编译得到的可执行文件
-
注意,在CMakeLists.txt文件中不要优化编译-O2,与调试会发送冲突,并添加可调试指令
-
点击左侧调试按钮,选择编译环境
-
选择配置
-
此时显示launch.json文件,替换program属性值为需要调试的可执行文件【绝对路径】
参数解释:
preLaunchTask
: 该参数定义调试器启动之前的执行任务。默认配置文件中可能并不包含该参数,我们需要手动添加,用于自动编译变更后的 C++ 代码。该字段的功能是根据taks.json文件自动编译新的可执行文件。tasks.json文件的目的就是做调试之前的编译工作,程序员无须反复编译
- 通过
terminal
->Configure Default Build Task
菜单,并选择Create tasks.json file from template
->Others
选项创建任务配置文件,文件创建位置为.vscode/tasks.json
,默认配置内容如下
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "echo",
"type": "shell",
"command": "echo Hello"
}
]
}
如:在build文件路径下自动执行camke和make指令。我们需要将任务配置文件修改为如下内容,
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"options": {
"cwd": "${workspaceFolder}/build"
},
"tasks": [
{
"type": "shell",
"label": "cmake",
"command": "cmake",
"args": [
".."
]
},
{
"label": "make",
"group": {
"kind": "build",
"isDefault": true
},
"command": "make",
"args": []
},
{
"label": "build",
"dependsOrder": "sequence",
"dependsOn": [
"cmake",
"make"
]
}
],
}
同时也要修改launch.json中的preLaunchTask字段:
- 此时再按下F5就会自动化调试,不用手动编译,会生成新的可执行文件进行调试
5. 补充:关于vscode的一些标识和快捷键
换行符的区别
高频使用快捷键:
在 Ctrl+P 窗口下还可以:
-
直接输入文件名,跳转到文件
-
? 列出当前可执行的动作
-
! 显示 Errors或 Warnings,也可以 Ctrl+Shift+M
-
: 跳转到行数,也可以 Ctrl+G 直接进入
-
@ 跳转到 symbol(搜索变量或 者函数),也可以 Ctrl+Shift+O 直接进入
-
@ 根据分类跳转 symbol,查找属性或函数,也可以 Ctrl+Shift+O 后输入:进入
-
#根据名字查找 symbol,也可以 Ctrl+T
快捷键:编辑器与窗口管理
-
打开一个新窗口:Ctrl+Shift+N
-
关闭窗口:Ctrl+Shift+W
-
同时打开多个编辑器(查看多个文件)
-
新建文件 Ctrl+N
-
文件之间切换 Ctrl+Tab
-
切出一个新的编辑器(最多 3 个) Ctrl+\,也可以按住 Ctrl 鼠标点击 Explorer 里的文件名
-
左中右 3 个编辑器的快捷键 Ctrl+1 Ctrl+2 Ctrl+3
3 个编辑器之间循环切换 Ctrl+
- 编辑器换位置, Ctrl+k然后按 Left或 Right
↓ 代码编辑相关的快捷键 ↓
快捷键:格式调整
-
代码行缩进 Ctrl+[ 、 Ctrl+]
-
Ctrl+C 、 Ctrl+V 复制或剪切当前行/当前选中内容
-
代码格式化:Shift+Alt+F,或 Ctrl+Shift+P 后输入 format code
-
上下移动一行:Alt+Up 或 Alt+Down
-
向上向下复制一行:Shift+Alt+Up 或 Shift+Alt+Down
-
在当前行下边插入一行 Ctrl+Enter
-
在当前行上方插入一行 Ctrl+Shift+Enter
快捷键:光标相关
-
移动到行首:Home
-
移动到行尾:End
-
移动到文件结尾:Ctrl+End
-
移动到文件开头:Ctrl+Home
-
移动到定义处:F12
-
定义处缩略图:只看一眼而不跳转过去 Alt+F12
-
移动到后半个括号:Ctrl+Shift+]
-
选择从光标到行尾:Shift+End
-
选择从行首到光标处:Shift+Home
-
删除光标右侧的所有字:Ctrl+Delete
-
扩展/缩小选取范围:Shift+Alt+Left 和 Shift+Alt+Right
-
多行编辑(列编辑):Alt+Shift+鼠标左键,Ctrl+Alt+Down/Up
-
同时选中所有匹配:Ctrl+Shift+L
-
Ctrl+D 下一个匹配的也被选中 (在 sublime 中是删除当前行,后面自定义快键键中,设置与 Ctrl+Shift+K 互换了)
-
回退上一个光标操作:Ctrl+U
快捷键:重构代码
-
找到所有的引用:Shift+F12
-
同时修改本文件中所有匹配的:Ctrl+F12
-
重命名:比如要修改一个方法名,可以选中后按 F2,输入新的名字,回车,会发现所有的文件都修改了
-
跳转到下一个 Error 或 Warning:当有多个错误时可以按 F8 逐个跳转
-
查看 diff:在 explorer 里选择文件右键 Set file to compare,然后需要对比的文件上右键选择 Compare with file_name_you_chose
快捷键:查找替换
-
查找 Ctrl+F
-
查找替换 Ctrl+H
-
整个文件夹中查找 Ctrl+Shift+F
快捷键:显示相关
-
全屏:F11
-
zoomIn/zoomOut:Ctrl +/-
-
侧边栏显/隐:Ctrl+B
-
显示资源管理器 Ctrl+Shift+E
-
显示搜索 Ctrl+Shift+F
-
显示 Git Ctrl+Shift+G
-
显示 Debug Ctrl+Shift+D
-
显示 Output Ctrl+Shift+U
固定打开的文件
- 双击标题栏或文件栏中的文件
参考博文:基于VSCode和CMake实现C/C++开发 | Linux篇