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)
  1. 编译源代码时需要加上 -g ,产生的可执行文件才能用 gdb 进行调试,例如:gcc -g main.cpp -o main
  2. 回车键:重复上一条命令

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:

  1. vscode中安装插件:cmake tools插件,cmake插件。C/C++ 插件

  2. 书写CMakeLists.txt,编译得到可执行文件:具体步骤查看博文:3.7.1 外部构建方式举例,然后调试通过CMake编译得到的可执行文件

  3. 注意,在CMakeLists.txt文件中不要优化编译-O2,与调试会发送冲突,并添加可调试指令
    在这里插入图片描述

  4. 点击左侧调试按钮,选择编译环境
    在这里插入图片描述

  5. 选择配置
    在这里插入图片描述

  6. 此时显示launch.json文件,替换program属性值为需要调试的可执行文件【绝对路径】
    在这里插入图片描述

参数解释:preLaunchTask: 该参数定义调试器启动之前的执行任务。默认配置文件中可能并不包含该参数,我们需要手动添加,用于自动编译变更后的 C++ 代码。该字段的功能是根据taks.json文件自动编译新的可执行文件。tasks.json文件的目的就是做调试之前的编译工作,程序员无须反复编译

  1. 通过 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字段:
在这里插入图片描述

  1. 此时再按下F5就会自动化调试,不用手动编译,会生成新的可执行文件进行调试

参考博文:基于VSCode和CMake实现C/C++开发 | Linux篇

Logo

更多推荐