Linux下的GDB调试工具

        GDB调试工具是Linux系统下的一款常用的调试工具,下面通过举例分析来深入了解GDB调试工具下的一些常见指令。

一、创建案例test.c

        创建该案例,本节之后使用GDB调试工具对该代码进行调试。

lyr@ubuntu:~/Desktop/GCCStudy$ code test.c
#include <stdio.h>

void my_print(int i){
    printf("print %d times!\n",i);
}
int main(int argc, char* argv[]){
    int i = 0;
    while(i < 10){
        i++;
        my_print(i);
    }
    return 0;
}

        运行一下看看!

lyr@ubuntu:~/Desktop/GCCStudy$ gcc test.c -o test
lyr@ubuntu:~/Desktop/GCCStudy$ ./test
print 1 times!
print 2 times!
print 3 times!
print 4 times!
print 5 times!
print 6 times!
print 7 times!
print 8 times!
print 9 times!
print 10 times!

二、基础指令

1. 进入代码调试工具

        通过如下两个命令,就进入到了代码调试工具。

gcc -g 文件名.c -o 可执行文件将调试信息放到可执行文件中
gdb 可执行文件GDB启动可执行文件
lyr@ubuntu:~/Desktop/GCCStudy$ gcc -g test.c -o test
lyr@ubuntu:~/Desktop/GCCStudy$ gdb test
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.2) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test...
(gdb) 

        出现上面的运行结果,就是进入到了调试表中。


2. 基础指令

(1)运行程序

  • run/r:运行程序
  • start:运行程序(到主函数停止)
  • p/print [变量名]:查看变量的值
  • ptype:查看变量类型

注 1:run和start的区别在于,run会将程序可执行的部分全部执行,而start则会将程序从上至下地执行,直到main语句停止执行。具体区别如下:

(gdb) start
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Temporary breakpoint 3 at 0x555555555171: file test.c, line 6.
Starting program: /home/lyr/Desktop/GCCStudy/test 

Temporary breakpoint 3, main (argc=21845, argv=0x0) at test.c:6
6       int main(int argc, char* argv[]){
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/lyr/Desktop/GCCStudy/test 
print 1 times!
print 2 times!
print 3 times!
print 4 times!
print 5 times!
print 6 times!
print 7 times!
print 8 times!
print 9 times!
print 10 times!

注 2:查看变量的值和类型,只有在程序逐行运行(n/s)的时候才能看到变量的值或类型。要知道GDB是代码的调试工具,里面的各种指令都是为了代码调试服务的,变量的值和类型事实上在程序执行时都是动态变化的,完全执行完的程序查看变量特征在代码调试这一块没有什么实际意义。

(gdb) start
Temporary breakpoint 1 at 0x555555555171: file test.c, line 7.
Starting program: /home/lyr/Desktop/GCCStudy/test 

Temporary breakpoint 1, main (argc=21845, argv=0x0) at test.c:7
7       int main(int argc, char* argv[]){
(gdb) n
8           int i = 0;
(gdb) p i
$1 = 0
(gdb) ptype i
type = int

(2)下一条指令

  • n/next:下一条指令(会越过函数)
  • s/step:下一条指令(会进入函数)
  • finish:  结束当前函数调用(当s进入函数体中,相当于退出函数体的功能)

注:n命令和s命令的区别在于,在执行程序时,n命令会直接跳过程序中调用函数的语句,而s命令会进入到定义好的函数的函数体中。具体区别如下:

------------------------------下面是start与n指令的使用------------------------------
(gdb) start
Temporary breakpoint 4 at 0x555555555171: file test.c, line 6.
Starting program: /home/lyr/Desktop/GCCStudy/test 

Temporary breakpoint 4, main (argc=21845, argv=0x0) at test.c:6
6       int main(int argc, char* argv[]){
(gdb) n
7           int i = 0;
(gdb) n
8           while(i < 10){
(gdb) n
9               i++;
(gdb) n
10              my_print(i);
(gdb) n
print 1 times!
8           while(i < 10){
(gdb) n
9               i++;
(gdb) n
10              my_print(i);
(gdb) n
print 2 times!
8           while(i < 10){
(gdb) n
9               i++;
(gdb) n
10              my_print(i);
(gdb) n
print 3 times!
8           while(i < 10){
(gdb) n
9               i++;
(gdb) n
10              my_print(i);
(gdb) n
##此处省略一万行代码##
print 10 times!
8           while(i < 10){
(gdb) n
12          return 0;
(gdb) n
13      }
(gdb) n
__libc_start_main (main=0x555555555171 <main>, argc=1, argv=0x7fffffffe2a8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, 
    stack_end=0x7fffffffe298) at ../csu/libc-start.c:342
342     ../csu/libc-start.c: No such file or directory.
(gdb) n
[Inferior 1 (process 10179) exited normally]
------------------------------下面是start与s指令的使用------------------------------
(gdb) start
Temporary breakpoint 5 at 0x555555555171: file test.c, line 6.
Starting program: /home/lyr/Desktop/GCCStudy/test 

Temporary breakpoint 5, main (argc=21845, argv=0x0) at test.c:6
6       int main(int argc, char* argv[]){
(gdb) s
7           int i = 0;
(gdb) s
8           while(i < 10){
(gdb) s
9               i++;
(gdb) s
10              my_print(i);
(gdb) s
my_print (i=21845) at test.c:3
3       void my_print(int i){
(gdb) s
4           printf("print %d times!\n",i);

        其中执行n命令时,由于test.c中存在for循环,所以需要循环执行10次,需要执行10次循环体中的内容,而由于n命令不能进入到函数体中,但是会执行函数体的功能,在本程序段中的功能就是输出“print %d times!”。

        当s命令进入到函数体之内时,可以通过finish命令结束函数调用:

(gdb) s
my_print (i=21845) at test.c:3
3       void my_print(int i){
(gdb) finish
Run till exit from #0  my_print (i=21845) at test.c:3
print 1 times!
main (argc=1, argv=0x7fffffffe2a8) at test.c:9
9           while(i < 10){

(3)断点调试

        断点是程序中的一个标记,当程序运行到断点时,会暂停执行,进入调试模式。

  • break/b 或 break [number]: b 20 在20行位置设置断点
  • d/delete [断点编号]:删除断点
  • continue/c:继续执行断点后续指令
  • info/i b:查看断点信息表
  • b 20 if i = 5:设置条件断点

(4)查看源码

  • list/l 或 list [数字]:列出源码。加数字,在指定行号位置附近显示
(gdb) list 5
1       #include <stdio.h>
2
3       void my_print(int i){
4           printf("print %d times!\n",i);
5       }
6
7       int main(int argc, char* argv[]){
8           int i = 0;
9           while(i < 10){
10              i++;

(5)退出GDB

  • quit/q:退出 gdb 当前调试

3. 其他指令

  • run:使用 run 查找段错误出现位置
  • set args 字串1 字串2 ...:设置 main 函数命令行参数 (在 start、run 之前)
  • run 字串1 字串2 ...:设置main函数命令行参数
  • bt/backtrace:列出当前程序正存活着的栈帧。(栈帧:随着函数调用在stack上开辟的一块内存空间,用于存放函数调用时产生的局部变量和临时值)
  • frame/f:根据栈帧编号,切换栈帧
  • display:设置跟踪变量
  • undisplay:取消设置跟踪变量,使用跟踪变量的编号

上面指令的功用小编在实际使用中正慢慢理解,敬请期待...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值