gdb调试常用指令及案例讲解

简介: GDB是一个由GNU开源组织发布的、UNIX/LINUX 操作系统下的、基于命令行的、功能强大的程序调试工具。

前言


GDB是一个由GNU开源组织发布的、UNIX/LINUX 操作系统下的、基于命令行的、功能强大的程序调试工具。


GDB 支持断点、单步执行、打印变量、观察变量、查看寄存器、查看堆栈等调试手段。在 Linux 环境软件开发中,GDB 是主要的调试工具,用来调试 C 和 C++ 程序(也支持 go 等其他语言)。


一、常用指令


-g:   使用该参数编译可以执行文件,得到调试表。
gdb ./a.out
list:     list 1 列出源码。根据源码指定 行号设置断点。
b:    b 20 在 20 行位置设置断点。
run/r:    运行程序
n/next:   下一条指令(会越过函数)
s/step:   下一条指令(会进入函数)
p/print:  p i 查看变量的值。
continue:继续执行断点后续指令。
finish:结束当前函数调用。
quit:退出 gdb 当前调试。


二、案例说明


使用 gdb 之前,要求对文件进行编译时增加 -g 参数,加了这个参数过后生成的编译文件会大一些,这是因为增加了 gdb 调试内容。


1、测试源文件


#include <stdio.h>
void myprint(int i)
{
    if (i % 2 == 1) {
        printf("this run, i = %d\n", i); 
    }   
}
int main(void)
{
    int i = 0;  
    printf("hello world\n");
    for (i = 0; i < 10; i++) {
        myprint(i);
    }   
}


2、编译和调试


①、编译

gcc test.c -o test -g

②、启动对 test 的调试

gdb test

list/l n 从第 n 行开始显示程序, 后续继续输入 list/l,就可以显示后面的代码

break/b n 在第 n 行设置断点,断点那一行不会执行

run/r 运行程序

接下来按 next/n/step/s 继续向下执行

next/n :下一个,调用函数就跑

step/s :单步,会进入调用的函数

要注意的是,如果是系统函数,按 s 就出不来了,这时用 until+行号直接执行到行号处

进到 printf 系统函数出不来的示例

使用 until 出来

print/p i 查看 i 变量的值

continue 直接运行到结束


三、其他指令


run:使用 run 查找段错误出现位置。
set args: 设置 main 函数命令行参数 (在 start、 run 之前)
run 字串 1 字串 2 ...: 设置 main 函数命令行参数
info b: 查看断点信息表
b 20 if i = 5: 设置条件断点。
ptype:查看变量类型。
bt:列出当前程序正存活着的栈帧。
frame: 根据栈帧编号,切换栈帧。
display:设置跟踪变量
undisplay:取消设置跟踪变量。 使用跟踪变量的编号


四、案例说明


1、将上述 main 函数做如下修改,制造段错误

int main(void)
{
    int i = 0;  
    char *p = "TEST";
    printf("hello world\n");
    p[0] = 'Q';
    for (i = 0; i < 10; i++) {
        myprint(i);
    }   
}
gcc test.c -o test -g
gdb test
run

可以看到段错误的位置

2、将上述 main 函数做如下修改,传参测试

int main(int argc, char *argv[])
{
    int i = 0;  
    printf("hello world\n");
    printf("argc = %d\n", argc);
    printf("argv[0] = %s, argv[1] = %s\n", argv[0], argv[1]);
    for (i = 0; i < 10; i++) {
        myprint(i);
    }   
}

命令行执行下述命令

gcc test.c -o test -g
gdb test
run

3、将上述 main 恢复成最初版本,做断点测试

int main(void)
{
    int i = 0;  
    printf("hello world\n");
    for (i = 0; i < 10; i++) {
        myprint(i);
    }   
}

设置两个断点,一个是普通断点(打在第14行),一个是条件断点(当 i = 6 时打在第6行),再执行 run

b 14
b 6 if i = 6
run

backtrace 命令是列出当前堆栈中的所有帧。在下面的例子中,栈上只有一帧,编号为0,属于 main 函数。

backtrace (或者bt)

接着,我们执行了 next 命令。下面我们继续通过 backtrace 命令来查看栈帧信息。

从上面输出结果,我们能够看出,有两个栈帧,第1帧属于 main 函数,第0帧属于 myprint 函数。

每个栈帧都列出了该函数的参数列表。从上面我们可以看出,main 函数没有参数,而 myprint 函数有参数,并且显示了其参数的值。


有一点我们可能比较迷惑,在第一次执行backtrace的时候,main 函数所在的栈帧编号为0,而第二次执行的时候,main 函数的栈帧为1,而 myprint 函数的栈帧为0,这是因为与栈的向下增长规律一致,我们只需要记住编号最小帧号就是最近一次调用的函数。


4、查看断点信息表 info b

5、栈帧 frame

栈帧用来存储函数的变量值等信息,默认情况下,GDB 总是位于当前正在执行函数对应栈帧的上下文中。

在前面的例子中,由于当前正在 myprint函数中执行,GDB 位于第0帧的上下文中。可以通过 frame 命令来获取当前正在执行的上下文所在的帧。

下面,我们尝试使用 print 命令打印下当前栈帧的值,如下:

如果我们想看其他栈帧的内容呢?比如 main 函数中的变量,那需要先切换栈帧再查看,我们可以通过 frame [num] 来切换栈帧,如下:

6、通过 ptype 查看变量的类型

7、通过 display 设置跟踪变量

和 print 命令一样,display 命令也用于调试阶段查看某个变量或表达式的值,它们的区别是,使用 display 命令查看变量或表达式的值,每当程序暂停执行(例如单步执行)时,GDB 调试器都会自动帮我们打印出来,而 print 命令则不会。


也就是说,使用 1 次 print 命令只能查看 1 次某个变量或表达式的值,而同样使用 1 次 display 命令,每次程序暂停执行时都会自动打印出目标变量或表达式的值。因此,当我们想频繁查看某个变量或表达式的值从而观察它的变化情况时,使用 display 命令可以一劳永逸。

undisplay:取消设置跟踪变量。 使用跟踪变量的编号


相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
目录
相关文章
|
3月前
|
NoSQL Linux C语言
Linux GDB 调试
Linux GDB 调试
64 10
|
3月前
|
NoSQL Linux C语言
嵌入式GDB调试Linux C程序或交叉编译(开发板)
【8月更文挑战第24天】本文档介绍了如何在嵌入式环境下使用GDB调试Linux C程序及进行交叉编译。调试步骤包括:编译程序时加入`-g`选项以生成调试信息;启动GDB并加载程序;设置断点;运行程序至断点;单步执行代码;查看变量值;继续执行或退出GDB。对于交叉编译,需安装对应架构的交叉编译工具链,配置编译环境,使用工具链编译程序,并将程序传输到开发板进行调试。过程中可能遇到工具链不匹配等问题,需针对性解决。
102 3
|
3月前
|
NoSQL
技术分享:如何使用GDB调试不带调试信息的可执行程序
【8月更文挑战第27天】在软件开发和调试过程中,我们有时会遇到需要调试没有调试信息的可执行程序的情况。这可能是由于程序在编译时没有加入调试信息,或者调试信息被剥离了。然而,即使面对这样的挑战,GDB(GNU Debugger)仍然提供了一些方法和技术来帮助我们进行调试。以下将详细介绍如何使用GDB调试不带调试信息的可执行程序。
107 0
|
5月前
|
NoSQL Linux C语言
Linux gdb调试的时候没有对应的c调试信息库怎么办?
Linux gdb调试的时候没有对应的c调试信息库怎么办?
44 1
|
5月前
|
NoSQL Linux C语言
Linux gdb调试的时候没有对应的c调试信息库怎么办?
Linux gdb调试的时候没有对应的c调试信息库怎么办?
31 0
|
5月前
|
NoSQL Linux C++
Linux C/C++ gdb调试正在运行的程序
Linux C/C++ gdb调试正在运行的程序
|
5月前
|
NoSQL Linux C++
Linux C/C++ gdb调试core文件
Linux C/C++ gdb调试core文件
|
5月前
|
NoSQL Linux C++
Linux C/C++ gdb调试
Linux C/C++ gdb调试
|
6月前
|
NoSQL Ubuntu 测试技术
【GDB自定义指令】core analyzer结合gdb的调试及自定义gdb指令详情
【GDB自定义指令】core analyzer结合gdb的调试及自定义gdb指令详情
95 1
|
6月前
|
NoSQL 编译器 C语言
【GDB调试技巧】提高gdb的调试效率
【GDB调试技巧】提高gdb的调试效率
82 1
下一篇
无影云桌面