侧边栏壁纸
Linux入门自学网博主等级

每日学一条Linux命令,终成Linux大神

  • 累计撰写 725 篇文章
  • 累计创建 143 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Linux gdb命令教程:如何使用gdb调试C, C++和Python程序(附实例详解和注意事项)

Linux gdb命令介绍

gdb是GNU Debugger的缩写,它是一个用来调试程序的工具,可以让你检查程序运行时的内部状态,设置断点,单步执行,修改变量值等,从而帮助你发现和修复程序的错误。gdb支持多种编程语言,如C,C++,Java,Fortran等,也可以调试多线程,多进程,远程程序等。

Linux gdb命令适用的Linux版本

gdb命令在大多数Linux发行版中都是默认安装的,你可以使用gdb --version命令来查看你的系统中的gdb版本。如果你的系统中没有安装gdb,你可以使用以下命令来安装:

  • 在基于Debian的系统中(如Ubuntu),使用sudo apt-get install gdb命令
  • 在基于Red Hat的系统中(如CentOS,Fedora),使用sudo yum install gdb命令(CentOS 7及以下版本)或sudo dnf install gdb命令(CentOS 8及以上版本)
  • 在基于Arch的系统中(如Manjaro),使用sudo pacman -S gdb命令

安装完成后,你可以使用gdb命令来启动gdb调试器,或者使用gdb program命令来调试一个可执行文件program。

Linux gdb命令的基本语法

gdb命令的基本语法如下:

gdb [options] [program] [core] [pid]

其中,options是一些可选的参数,用来控制gdb的行为,如-q表示安静模式,不显示版权信息和警告信息,-tui表示使用文本用户界面,-x file表示从文件中执行gdb命令等。program是要调试的可执行文件的名称,如果没有指定,可以在gdb中使用file命令来加载。core是一个core dump文件,用来分析程序崩溃时的状态,如果没有指定,可以在gdb中使用core命令来加载。pid是一个进程的ID,用来附加到一个正在运行的进程上,如果没有指定,可以在gdb中使用attach命令来附加。

Linux gdb命令的常用选项或参数说明

gdb命令有很多选项或参数,这里只列举一些常用的:

选项或参数说明
-q安静模式,不显示版权信息和警告信息
-tui使用文本用户界面,可以在终端中显示源代码和寄存器等信息
-x file从文件中执行gdb命令,file是一个包含gdb命令的文本文件
-ex command在启动gdb后执行一条gdb命令,command是一个gdb命令,可以使用多个-ex选项来执行多条命令
-args args将args作为要调试的程序的参数,args是一个或多个参数,用空格分隔
-p pid附加到一个正在运行的进程上,pid是一个进程的ID
-c core使用一个core dump文件,core是一个core dump文件的名称
-s symbols使用一个符号表文件,symbols是一个符号表文件的名称,通常是一个.o文件
-d directory将directory添加到源代码搜索路径中,directory是一个目录的名称,可以使用多个-d选项来添加多个目录
-n不读取任何初始化文件,如~/.gdbinit
-h显示帮助信息

Linux gdb命令的实例

实例1:启动gdb并加载一个可执行文件

如果你有一个可执行文件,比如hello,你可以使用以下命令来启动gdb并加载该文件:

gdb hello

这样,你就可以在gdb中使用各种命令来调试hello程序了。

实例2:在gdb中运行一个程序

如果你已经在gdb中加载了一个可执行文件,比如hello,你可以使用以下命令来运行该程序:

(gdb) run

这样,你就可以看到程序的输出,如果程序正常结束,你会看到类似这样的信息:

[Inferior 1 (process 1234) exited normally]

如果程序遇到错误,你会看到类似这样的信息:

Program received signal SIGSEGV, Segmentation fault.
0x00000000004005f4 in main () at hello.c:10
10	    *p = 0;

这表示程序在第10行发生了段错误,你可以使用backtrace命令来查看函数调用栈,或者使用print命令来查看变量的值等。

实例3:在gdb中设置断点

如果你想在程序运行到某个位置时暂停,你可以使用break命令来设置断点,断点可以是一个函数名,一个源代码文件名和行号,一个地址等。比如,你可以使用以下命令来设置断点:

(gdb) break main
Breakpoint 1 at 0x4005ed: file hello.c, line 6.

这表示在main函数的第6行设置了一个断点,当程序运行到这里时,会停下来,你可以使用continue命令来继续运行,或者使用delete命令来删除断点等。

实例4:在gdb中单步执行

如果你想逐行执行程序,你可以使用next命令或step命令,区别在于,next命令会将函数调用作为一条语句执行,而step命令会进入函数内部执行。比如,你可以使用以下命令来单步执行:

(gdb) next
7	    int *p = NULL;
(gdb) step
8	    foo();
(gdb) step
foo () at hello.c:3
3	    printf("Hello, world!\n");

这表示先执行了第7行,然后执行了第8行,由于使用了step命令,所以进入了foo函数内部,执行了第3行。

实例5:在gdb中修改变量的值

如果你想在调试过程中修改变量的值,你可以使用set命令或print命令,区别在于,set命令只修改变量的值,而print命令还会显示变量的值。比如,你可以使用以下命令来修改变量的值:

(gdb) print x
$1 = 10
(gdb) set x = 20
(gdb) print x
$2 = 20
(gdb) print x = 30
$3 = 30
(gdb) print x
$4 = 30

这表示先打印了变量x的值,然后使用set命令将x的值改为20,再打印了x的值,然后使用print命令将x的值改为30,并显示了x的值,再打印了x的值。

实例6:在gdb中查看寄存器的值

如果你想查看程序运行时的寄存器的值,你可以使用info registers命令或print命令,区别在于,info registers命令会显示所有的寄存器的值,而print命令只会显示一个寄存器的值。比如,你可以使用以下命令来查看寄存器的值:

(gdb) info registers
rax            0x0                 0
rbx            0x0                 0
rcx            0x0                 0
rdx            0x0                 0
rsi            0x0                 0
rdi            0x0                 0
rbp            0x0                 0x0
rsp            0x7fffffffe1f0      0x7fffffffe1f0
r8             0x0                 0
r9             0x0                 0
r10            0x0                 0
r11            0x0                 0
r12            0x0                 0
r13            0x0                 0
r14            0x0                 0
r15            0x0                 0
rip            0x4005f4            0x4005f4 <main+7>
eflags         0x10202             [ IF RF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
(gdb) print $rax
$1 = 0

这表示先显示了所有的寄存器的值,然后显示了rax寄存器的值,你可以使用$符号来引用寄存器的名称。

实例7:在gdb中查看内存的内容

如果你想查看程序运行时的内存的内容,你可以使用x命令,它的语法如下:

x/nfu address

其中,n是一个数字,表示要显示的内存单元的个数,f是一个格式字符,表示要显示的内存单元的格式,u是一个单位字符,表示要显示的内存单元的大小,address是一个内存地址,可以是一个变量名,一个寄存器名,一个表达式等。比如,你可以使用以下命令来查看内存的内容:

(gdb) x/4xb &x
0x7fffffffe1ec: 0x0a    0x00    0x00    0x00
(gdb) x/1dw $rsp
0x7fffffffe1f0: 0x0000000000000000

这表示先显示了变量x的地址开始的4个字节的内容,以十六进制和字节为单位,然后显示了rsp寄存器的值开始的一个双字的内容,以十进制和双字为单位。

实例8:在gdb中使用条件断点

如果你想在程序运行到满足某个条件的位置时暂停,你可以使用break命令的if子句来设置条件断点,条件可以是一个表达式,一个变量的值,一个寄存器的值等。比如,你可以使用以下命令来设置条件断点:

(gdb) break 10 if i == 5
Breakpoint 2 at 0x4005f7: file hello.c, line 10.

这表示在第10行设置了一个条件断点,当变量i的值等于5时,程序会停下来。你可以使用info breakpoints命令来查看所有的断点信息,或者使用condition命令来修改或删除断点的条件等。

实例9:在gdb中使用观察点

如果你想在程序运行时监视一个变量或一个表达式的值的变化,你可以使用watch命令来设置观察点,当变量或表达式的值发生变化时,程序会停下来。比如,你可以使用以下命令来设置观察点:

(gdb) watch x
Hardware watchpoint 3: x

这表示设置了一个观察点,当变量x的值发生变化时,程序会停下来。你可以使用info watchpoints命令来查看所有的观察点信息,或者使用delete命令来删除观察点等。

实例10:在gdb中使用信号

如果你想在程序运行时发送或处理一个信号,你可以使用signal命令或handle命令,区别在于,signal命令会向程序发送一个信号,而handle命令会设置对一个信号的处理方式。比如,你可以使用以下命令来使用信号:

(gdb) signal SIGINT
Continuing with signal SIGINT.
Program received signal SIGINT, Interrupt.
0x00007ffff7aef9d0 in __GI___nanosleep (requested_time=requested_time@entry=0x7fffffffe1f0, remaining=remaining@entry=0x7fffffffe1f0) at ../sysdeps/unix/sysv/linux/nanosleep.c:28
28      ../sysdeps/unix/sysv/linux/nanosleep.c: No such file or directory.
(gdb) handle SIGINT nostop
Signal        Stop      Print   Pass to program Description
SIGINT        No        Yes     Yes             Interrupt
(gdb) continue
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x00007ffff7aef9d0 in __GI___nanosleep (requested_time=requested_time@entry=0x7fffffffe1f0, remaining=remaining@entry=0x7fffffffe1f0) at ../sysdeps/unix/sysv/linux/nanosleep.c:28
28      in ../sysdeps/unix/sysv/linux/nanosleep.c

这表示先向程序发送了一个SIGINT信号,程序收到信号后停下来,然后使用handle命令将SIGINT信号的处理方式设置为不停止,继续运行,再次向程序发送了一个SIGINT信号,程序收到信号后不停止,继续运行。

Linux gdb命令的注意事项

  • gdb命令需要在编译时使用-g选项来生成调试信息,否则无法显示源代码和变量等信息。
  • gdb命令在调试多线程或多进程的程序时,需要使用一些特殊的命令,如info threadsthreadinfo inferiorsinferior等,来切换或控制不同的线程或进程。
  • gdb命令在调试远程程序时,需要使用target命令来连接到远程目标,远程目标可以是一个串口,一个网络接口,一个仿真器等,具体的连接方式取决于远程目标的协议和配置。
  • gdb命令在调试动态库时,需要使用set solib-search-path命令来设置动态库的搜索路径,或者使用set sysroot命令来设置系统根目录,否则无法加载动态库的符号表和源代码等信息。
  • gdb命令在调试程序时,可能会遇到一些错误或警告信息,如No symbol table is loaded. Use the "file" command.No source file named hello.c.No line 10 in the current file.等,这些信息通常表示gdb无法找到相应的文件或符号,需要检查文件的路径和名称,或者重新编译程序等。
  • 如果在调试过程中,出现bash: gdb: command not found的错误信息,表示系统中没有安装gdb,需要根据系统的类型和版本,使用相应的命令来安装gdb。

Linux gdb相关命令

1

评论区