0


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

文章目录


前言

  • 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>voidmyprint(int i){if(i %2==1){printf("this run, i = %d\n", i);}}intmain(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 20if i =5: 设置条件断点。
ptype:查看变量类型。
bt:列出当前程序正存活着的栈帧。
frame: 根据栈帧编号,切换栈帧。
display:设置跟踪变量
undisplay:取消设置跟踪变量。 使用跟踪变量的编号

四、案例说明

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

intmain(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 6if 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:取消设置跟踪变量。 使用跟踪变量的编号
在这里插入图片描述


我的qq:2442391036,欢迎交流!

标签: linux

本文转载自: https://blog.csdn.net/qq_41839588/article/details/130236028
版权归原作者 须尽欢~~ 所有, 如有侵权,请联系我们删除。

“gdb调试常用指令及案例讲解”的评论:

还没有评论