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

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

  • 11
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值