GDB:从零开始入门GDB

目录

1.前言

2.开启项目报错

3.GDB的进入和退出

4.GDB调试中查看代码和切换文件

5.GDB调试中程序的启动和main函数传参

6.GDB中断点相关的操作

7.GDB中的调试输出指令

8.GDB中自动输出值指令

9.GDB中的调试指令


前言

在日常开发中,调试是我们必不可少的技能。在专业的编译器中,如VSCode,VS等编译器中都提供了较为完全的调试功能,如单步调试,异步调试等等。而在Linux中我们可以使用GDB工具来调试自己编写的代码,本篇文章就皆在讲解GDB的使用以及调试方法


开启项目报错

在关于《MinGW:从入门到链接库》的文章中,曾对如何开启代码调试,关闭调试进行简单的讲解,在对GDB调试工具讲解之前,先简单回顾以下这些内容

1.使用-W命令开启编译生成期间的警告

bash 复制代码
//开启编译生成期间的警告
g++ -o 可执行文件名 -W 源文件.cpp

图1.使用-W命令开启警告

2.使用-Wall命令开启编译生成期间的所有警告

bash 复制代码
//开启编译生成期间的所有警告
g++ -o 可执行文件名 -Wall 源文件.cpp

图2.使用-Wall命令开启警告

3.使用-Wunused-variable命令开启指定的Wunuser-variable警告和默认警告(其他指定的警告也可以通过修改-Wunused-variable的类型来修改)

bash 复制代码
//开启指定的wunuser-variable警告和默认警告
g++ -o 可执行文件名 -Wunused-variable 源文件.cpp

图3.使用-Wunused-variable命令开启默认警告和指定警告

4.使用-Wno命令关闭编译期间的指定警告

bash 复制代码
//关闭指定的return-local-addr警告和默认警告
g++ -o 可执行文件名 -Wno-return-local-addr 源文件.cpp

图4.使用-Wno命令关闭指定的return-local-addr警告

5.使用Werroe命令将编译生成期间的警告当作错误提示

bash 复制代码
//使用Werroe命令将编译生成期间的警告当作错误提示
g++ -o 生成的可执行文件名 -Werror 源文件.cpp

图5.使用-Werror命令将编译生成期间的警告当作错误提示

6.使用-O命令(大写)设置文件优化等级**,**其中优化等级共分为3个,优先级从1到3

bash 复制代码
//在编译生成期间对文件进行优化,优化等级为1
g++ -o 可执行文件名 -O1 源文件.cpp
 
//在编译生成期间对文件进行优化,优化等级为2
g++ -o 可执行文件名 -O2 源文件.cpp
 
//在编译生成期间对文件进行优化,优化等级为3
g++ -o 可执行文件名 -O3 源文件.cpp

图6.对编译源文件进行等级为1的优化


GDB的进入和退出

在启动GDB调试之前,需要先对项目进行编译生成可执行文件。此时为了能进入GDB调试,在编译器CPP文件时需要加入-g命令,为生成的可执行文件添加调试信息,具体代码如下:

bash 复制代码
g++ -g -o 可执行文件名 要编译文件

示例:g++ -g -o Demo2 txt1.cpp

图7.使用-g命令生成的可执行文件区别

生成可执行文件后,可以使用gdb命令进入调试界面,如下:

bash 复制代码
gdb 可执行文件名

示例:gdb Demo

图8.使用gdb命令进入GDB调试

在进入GDB调试后,可以使用quit命令退出GDB调试,如下:

bash 复制代码
quit

图9.退出GDB调试


GDB调试中查看代码和切换文件

在正式启动可执行文件前,我们一般需要先查看程序代码,找到合适的地方打断点,以下是几种查看代码和切换文件的方式:

1.使用list命令查看当前调试的文件(默认显示前10行)

bash 复制代码
list
list 指定的文件名:行号
list 指定的文件名:函数名

示例:list main:5  //查看main文件中的第五行(显示上下文代码)
示例:l main:fun   //仓库main文件中的fun函数
PS:也可以使用缩写l

图10.使用list命令查看代码

2.使用set listsize命令设置默认显示的行数

bash 复制代码
set listsize

示例 set listsize 20
PS:可简写为set list

3.使用show listsize命令显示当前的显示行数

bash 复制代码
show listsize

PS:可简写为 show list

图11.显示和设置的显示的行数

4.使用fram命令查看当前显示代码的位置(可防止频繁调用list查看代码显示范围越界):

bash 复制代码
fram

图12.查看当前显示的行数


GDB调试中程序的启动和main函数传参

在使用gdb命令进入GDB调试后,可以使用以下两种方式启动程序:

1.使用run命令启动程序(执行到断点位置,无断点则全部执行):

bash 复制代码
run

图13.使用run命令启动程序

2.使用start命令启动程序(执行到程序的第一行代码):

bash 复制代码
stars

图14.使用start命令启动程序

一般我们在调试可执行文件时,需要传入参数,而且main函数也自带两个参数分别是int型的argc对象和char*型的argv对象,我们可以使用以下命令对其传参和显示当前传入参数:

1.使用set args命令传入参数

bash 复制代码
set args 传入的参数

示例:sey args 1 2 3

2.使用show args命令显示当前传入的参数

bash 复制代码
show args

图15.设置参数和显示参数


GDB中断点相关的操作

断点的类型分为两种,一个是条件断点,即满足指定条件则在该断点处停止,二是常规断点,程序运行到该位置便停止。在GDB中可以将断点设置到具体的行中,也可以设置到具体的函数中,具体参考如下:

1.使用break命令设置断点

bash 复制代码
break 行数(函数名)

示例: break 10
示例: b fun
PS:可使用简写b

图16.设置断点

2.使用break命令设置条件断点

bash 复制代码
break 行数 if 条件

示例:break 5 if i == 2

3.使用break命令设置其他文件的断点

bash 复制代码
break 文件名:行数(函数名)

示例:break main:5

设置完断点后,可以取消设置的断点以及查看当前调试的断点信息,具体操作如下:

1.使用info break命令查看断点信息

bash 复制代码
info break

PS:可简写为i b

图17.查看断点信息

2.使用delete命令删除断点

bash 复制代码
delete 断点编号

示例:delete 1
PS:可简写为d

图18.删除指定断点

3.使用disable命令设置断点的状态为无效

bash 复制代码
disable 断点编号

示例:disable 1    //设置编号为1的无效
示例:disable 1-3  //设置编号为1到3的无效
PS:可简写为dis

图19.使用disable命令设置断点状态为无效

4.使用enable命令设置断点状态为有效

bash 复制代码
enable 断点编号

示例:enable 1    //设置编号为1的断点生效
示例:enable 1-3  //设置编号为1到3的生效
PS:可简写为ena

图20.使用enable命令设置断点状态为有效


GDB中的调试输出指令

在GDB中我们可以使用run和start指令来启动程序,当遇到断点时会停止,继续输入run或者start指令,则会提示我们是否要重新执行该程序。如果要继续执行则要使用continue指令,具体如下:

1.使用continue指令继续运行程序

bash 复制代码
continue

PS:可简写为c

图21.使用continue命令继续执行程序

在调试过程中,我们在代码中也可能会经常使用printf或者cout函数来输出代码中执行的变量信息,这样能实时的观察到变量值的变化,方便我们定位代码的Bug。而在GDB中我们也可以做类似的操作,具体如下:

1.使用print指令输出指定变量的值

在使用print指令输出变量的值的时候,我们可以使用格式化字符限制输出的字符格式,类似于C语言中的scanf函数,具体格式化字符信息如下:

|-------|-------------------|
| 格式化字符 | 备注 |
| /x | 以十六进制的形式打印出整数 |
| /o | 以八进制的形式打印出整数 |
| /t | 以二进制的形式打印出整数 |
| /f | 以浮点数的形式打印变量或表达式的值 |
| /c | 以字符形式打印变量或表达式的值 |
| /d | 以有符号、十进制的形式打印出整数 |
| /u | 以无符号、十进制的形式打印出整数 |

表1.格式化字符表

使用print命令前,需要先给程序打上断点,并且使用run或start指令启动程序,当运行到断点时,即可使用print指令查看对象的值

bash 复制代码
print 变量名
print 格式化字符 变量名

示例:print obj
示例:p /x obj
PS:可简写为p

图22.使用print命令输出指定对象的值

2.使用ptype命令输出指定的变量的类型

bash 复制代码
ptype 变量名

示例:ptype obj 

图23.使用ptype命令输出指定对象的类型


GDB中自动输出值指令

在GDB调试中,我们会经常遇到循环,为了方便输出循环中的值,我们可以使用print指令输出,但是每一次执行后都执行一遍print指令则会十分麻烦。这时我们可以display指令自动输出指定变量的值,具体如下:

1.使用display命令自动输出指定变量的值

使用display命令输出变量的值,也可以使用格式化字符输出,具体可参考print指令的格式化字符表(表1),具体操作如下:

bash 复制代码
display 变量名
display 格式化字符

示例:display obj

图24.使用display命令自动输出指定对象的值

2.使用info命令输出自动显示表(使用display指令指定输出过的对象的值):

bash 复制代码
info display

图25.使用info命令输出自动显示表

3.使用undisplay指令删除指定变量的自动输出

bash 复制代码
undisplay 变量编号

示例:undisplay 1

4.使用disable指令将自动输出变量的状态设为禁用

bash 复制代码
disable 变量编号

示例:disble 1

5.使用enable指令将自动输出变量的状态设为启用

bash 复制代码
enable 变量编号

示例:enable 1

PS:具体可以参考断点中相关的操作


GDB中的调试指令

我们在使用各种编译器进行调试时,会提供一些类似于单步调试等功能,而GDB也同样支持这些功能,具体如下:

1.使用step命令执行下一行代码(当遇到函数时,将跳转至函数体内):

bash 复制代码
step

PS:可简写为s

2.使用finish命令跳出函数体(使用step命令执行到函数体内部时,使用该指令跳出函数体。PS:保证函数体内不存在断点,若存在断点则还是执行该函数体内的代码):

bash 复制代码
finsh

3.使用next命令执行下一行代码(当遇到函数时,不会跳转至函数体内):

bash 复制代码
next

PS:可简写为n

4.使用unit跳出循环体(当断点在循环内时,可以使用该指令):

bash 复制代码
unit
相关推荐
迷迭所归处14 分钟前
C++ —— 关于vector
开发语言·c++·算法
架构文摘JGWZ42 分钟前
Java 23 的12 个新特性!!
java·开发语言·学习
leon62543 分钟前
优化算法(一)—遗传算法(Genetic Algorithm)附MATLAB程序
开发语言·算法·matlab
CV工程师小林43 分钟前
【算法】BFS 系列之边权为 1 的最短路问题
数据结构·c++·算法·leetcode·宽度优先
white__ice2 小时前
2024.9.19
c++
天玑y2 小时前
算法设计与分析(背包问题
c++·经验分享·笔记·学习·算法·leetcode·蓝桥杯
锦亦之22332 小时前
QT+OSG+OSG-earth如何在窗口显示一个地球
开发语言·qt
我是苏苏2 小时前
Web开发:ABP框架2——入门级别的增删改查Demo
java·开发语言
姜太公钓鲸2332 小时前
c++ static(详解)
开发语言·c++
菜菜想进步2 小时前
内存管理(C++版)
c语言·开发语言·c++