GDB调试

前言

在编写程序过程中可能遇到语法错误或者逻辑错误,语法错误可以通过编译器帮助我们检查出来,但是逻辑错误需要我们自己去发现。一般解决代码的逻辑问题除了加一些打印信息以外,还可以借助一些调试工具,下面为大家介绍一款常用的调试工具GDB。

什么是GDB

1.1 关于gdb

GDB(GNU Debugger),从名称上可以看出,它诞生于 GNU 计划(同时诞生的还有 GCC、Emacs 等)。GDB是 Linux 下常用的程序调试器,并且是一款功能强大的开源调试工具,广泛用于C、C++、Fortran等编程语言的调试。它可以帮助开发者在程序运行过程中进行断点设置、变量查看、内存监测等操作,以及跟踪程序的执行流程。

1.2 gdb的作用

下面介绍一些GDB调试工具常用的功能:

  1. 断点设置:通过在代码中设置断点,可以让程序在指定位置停下来,方便我们观察变量值、执行路径等信息。GDB支持多种类型的断点设置,如函数断点、条件断点、临时断点等。
  2. 变量查看:GDB可以查看当前程序中各个变量的值,并且支持对变量进行修改。这对于排查逻辑错误非常有帮助,可以实时监测变量值是否符合预期。
  3. 回溯堆栈:当程序出现崩溃或异常情况时,GDB可以帮助我们获取堆栈信息。通过回溯堆栈,我们可以了解导致程序崩溃的原因所在,并进行相应修复。
  4. 内存监测:GDB提供了一系列内存监测功能,包括检测内存泄漏、检查数组越界访问、查看内存映射等。这些功能可以帮助开发者及时发现和解决与内存相关的问题。
  5. 多线程调试:对于多线程程序,GDB可以支持对多个线程的调试。开发者可以通过GDB查看各个线程的状态、堆栈信息,并进行线程间的切换和同步操作。
  6. 远程调试:GDB还支持远程调试,即在一台机器上运行GDB服务器,另一台机器上

运行GDB客户端。这样可以方便地在远程机器上进行调试操作,而不需要将代码复制到本地进行调试。

总之,GDB是一个强大且灵活的调试工具,它提供了丰富的功能来帮助开发者定位和解决程序中的问题。通过合理利用GDB,我们可以更高效地进行程序调试,并提高软件质量和开发效率。如果你是一个编程爱好者或者专业开发人员,不妨尝试使用GDB来提升自己的调试能力吧!

调试步骤 

        1. 第一步:加调试信息

        启动gdb调试前,需要在编译时加上-g参数,保留调试信息(比如各行代码所在的行号、包含程序中所有变量名称的列表(又称为符号表)等),否则不能使用GDB进行调试。例如为demo.c加上调试信息然后进行编译执行以下命令:

生成默认的a.out

可以用readelf查看是否有debug调试信息:

如:

如果文件a.out没有调试信息,即输入该命令到终端没有输出内容,则无法被调试。

        2. 第二步:启动gdb调试

  1. 若调试程序无参数,则直接gdb加程序名进入gdb调试模式。

然后用命令run运行程序即可。例如, 有以下程序:

gcc -g加调试并且编译生成a.out,然后用gdb a.out进入gdb调试:

  1. 若调试程序有参数,则编译和启动gdb步骤一样,只不过用run运行时后面加参数,如下图所示:

gdb的用法 

常用gdb命令 

gdb的使用方式是通过各种命令,下面是gdb常用的命令:

调试命令(缩写)

作用

break(b)

在源代码指定某行设置断点,可以加指定位置。

run(r)

执行被调试程序,会停在第一个断点处。

continue(c)

当程序停在某一断点处时,可以用该命令执行到下一个断点,若没有下一个断点则结束程序。

next(n)

单步跳过,让程序一行一行执行。

step(s)

单步运行,如果有调用函数,则进入调用函数内,否则和next命令一样一行一行执行程序。

print(p)

打印变量的值,后面跟变量名,若打印指针内容则用*加指针名。

list(l)

显示程序代码内容,包括行号。

unitl(u)

若遇到循环内断点不想继续追踪,可以用次命令运行完循环体。

unitl(u) n

n为某一行代码行号,此命令会直接跳到改行停止。

finish(fi)

结束当前正在执行函数,并在跳出函数后暂停程序的执行。

return(return)

结束当前调用函数并返回指定值,到上一次函数调用处停止。

jump(j)

使程序从当前要执行的代码处,直接跳转到指定位置处继续执行后续代码。

quit(q)

退出gdb调试

Info

后面可以跟随不同的参数,以获取不同类型的信息, 比如查看断点信息info b

 gdb添加断点

        添加断点可以帮助我们更方便的锁定bug位置,下面介绍一下如何添加断点:

b filename.c:n

在文件filename.c的第n行设置断点

b function_name

在函数function_name开头设置断点

b *addr

在内存地址addr处设置断点

案例,有以下程序:

进行gdb调试:

查看断点信息:info b

删除断点n: delete(d) n

禁用断点n: disable n

使能断点n: enable n

观察断点

GDB调试器不光可以打普通断点还可以打观察断点,观察断点可以监控变量或表达式的值的变化。观察断点用命令watch去设置。

使用 GDB 调试程序的过程中,可以借助观察断点来监控程序中某个变量或者表达式的值,只要发生改变,程序就会停止执行。相比普通断点,观察断点不需要我们预测变量(表达式)值发生改变的具体位置,而是直接加变量名或表达式。

watch expr

为表达式(变量)expr设置一个观察点。一量表达式值有变化时,马上停住程序。

rwatch expr

当表达式(变量)expr被读时,停住程序。

awatch expr

当表达式(变量)的值被读或被写时,停住程序。

info watchpoints

查看观察点、断点和捕捉点信息,同info break 一样.

案例:

条件断点

当我们需要在特定条件下暂停程序的执行时,可以使用gdb设置条件断点。而条件断点可以在满足特定条件时触发,使程序停止在设定的断点处,方便我们进行调试工作。下面介绍如何设置条件断点:

在指定文件和的第n行上设置条件断点:b filename.c:n if <expr>

例如:

当在i等于3时,程序将会在第7行断住, 可以写成i==3也可以写成i=3。

若要修改断点条件可以用condtion命令,用法:

condition 断点号 修改条件

例如,之前设置b==3时产生该断点,那么使用condition可以修改断点产生的条件。

info命令

info可以用于获取程序执行状态的信息。info 指令后面可以跟随不同的参数,以获取不同类型的信息。使用 info 指令可以帮助开发者了解程序的执行状态,包括断点、变量、堆栈、寄存器、线程等信息。这些信息对于程序的调试和分析还是非常有用的。

以下是 info 指令常用的参数和其含义:

info breakpoints

显示当前设置的断点信息,包括断点编号、断点位置、断点条件等。

info watchpoints

显示当前设置的观察点信息,即监视变量的值的变化。

info frame

显示当前函数的堆栈帧信息,包括函数名、参数、局部变量等。

info locals

显示当前函数的局部变量的值。

info registers

显示当前程序执行时的寄存器状态,包括通用寄存器、特殊寄存器等。

info threads

显示当前线程的信息,包括线程编号、线程状态等。

info inferiors

显示当前程序的进程信息,包括进程编号、进程状态等。

info program

显示程序的加载地址和执行路径等信息。

info sharedlibrary

显示已加载的共享库的信息。

info source

显示当前源文件的信息,包括文件名、行数等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值