A debugger plays a vital role in any software development system. Nobody can write a bug-free code all at once. During the course of development, bugs are being raised and needs to be solved for further enhancement. A development system is incomplete without a debugger. Considering the open source developers community, GNU Debugger is their best choice. It is also used for commercial software development on UNIX type platforms.

GNU调试器,也被称为gdb,允许我们在代码执行时进行调试,或者查看程序在崩溃前试图做什么。GDB基本上帮助我们做四件主要的事情来捕捉源代码中的缺陷。
- 启动程序,指定可能影响一般行为的参数。
- 在指定条件下停止程序。
- 检查崩溃或程序停止时的情况。
- 更改代码,并即时实验修改后的代码。
我们可以使用gdb轻松调试用C和C++编写的程序。目前对其他编程语言如D、Modula-2、Fortran的支持是部分的。
开始使用GNU调试器或GDB
GDB是通过gdb命令调用的。在发出gdb命令后,会显示一些关于平台的信息,并将您进入(gdb)提示符中,如下所示。
[root@fedora20 ~]# gdb
示例输出
GNU gdb (GDB) Fedora 7.6.50.20130731-19.fc20 Copyright (C) 2013 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-redhat-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". (gdb)
键入 help list 以输出gdb内可用的不同命令类别。键入 help ,后接类名以获取该类别中的命令列表。键入 help all 以获取所有命令的列表。如果命令名不歧义,允许使用命令名的缩写。例如,您可以键入 n 而不是键入 next,或者键入 c 而不是键入 continue,依此类推。
最常用的GDB命令
常用的gdb命令列在下表中。这些命令应该从gdb命令提示符(gdb)中使用。
Command
|
Description
|
run
|
Start a program execution
|
quit
|
Quit gdb
|
print expr
|
Print expression where expr may be a variable name too
|
next
|
Go to next line
|
step
|
Step into next line
|
continue
|
Continue from the current line till the end of program or next break point
|
请注意step和next这两个命令之间的区别。next命令如果下一行是一个函数调用,则不会进入函数。而step命令可以进入函数并查看函数内部发生了什么。
A sample session with GDB
考虑以下源代码。
// sum.c #include <stdio.h> int sum (int a, int b) { int c; c = a + b; return c; } int main() { int x, y, z; printf("\nEnter the first number: "); scanf("%d", &x); printf("Enter the second number: "); scanf("%d", &y); z = sum (x, y); printf("The sum is %d\n\n", z); return 0; }
为了调试输出文件,我们需要使用-g选项来编译相同的gcc代码如下。
$ gcc -g sum.c -o sum
输出文件sum可以通过以下两种方式之一附加到gdb:
1. 通过将输出文件作为gdb的参数来指定输出文件。
$ gdb sum
2. 使用file命令在gdb中运行输出文件。
$ gdb (gdb) file sum
list命令列出源代码文件中的行并移动指针。因此,首先list 将显示前10行,然后list显示接下来的10行,依此类推。
(gdb) list 1 #include <stdio.h> 2 3 int sum (int a, int b) { 4 int c; 5 c = a + b; 6 return c; 7 } 8 9 int main() { 10 int x, y, z;
要开始执行,请发出run 命令。现在程序正常执行。但是我们忘记在源代码中设置一些断点来调试了,是吗?这些断点可以为函数或指定的行指定。
(gdb) b main
注意:我使用了b作为break的缩写。
在主函数设置断点后,重新运行程序将会停在第11行。如果知道行号,也可以实现同样的效果。
(gdb) b sum.c:11
现在通过使用next或n命令逐行执行代码。需要注意的是next命令不会进入函数代码,除非在函数上设置了断点。现在尝试使用print命令。在函数sum上设置断点如下。
(gdb) b sum Breakpoint 1 at 0x4005aa: file sum.c, line 5. (gdb) r Starting program: /root/sum Enter the first number: 2 Enter the second number: 3 Breakpoint 1, sum (a=2, b=3) at sum.c:5 5 c = a + b; (gdb) p a $1 = 2 (gdb) p b $2 = 3 (gdb) c Continuing. The sum is 5 [Inferior 1 (process 3444) exited normally]
如果正在运行的程序需要命令行参数,则需要在run命令中提供相应的参数。
(gdb) run . . .
与当前运行程序相关的共享库文件可以列出如下。
(gdb) info share From To Syms Read Shared Object Library 0x00000035a6000b10 0x00000035a6019c70 Yes /lib64/ld-linux-x86-64.so.2 0x00000035a641f560 0x00000035a6560bb4 Yes /lib64/libc.so.6
修改变量
GDB还可以在程序执行过程中修改变量。让我们尝试一下。如上所述,在第16行设置断点并运行程序。
(gdb) r Starting program: /root/sum Enter the first number: 1 Enter the second number: 2 Breakpoint 1, main ( ) at sum.c:16 16 printf("The sum is %d\n\n", z); (gdb) set z=4 (gdb) c Continuing. The sum is 4
现在a=1,b=2,结果应该是z=3。但是在主函数中我们将最终结果更改为z=4。通过这种方式,使用GDB可以更容易地进行调试。
启用/禁用断点
要获取所有断点的列表,请键入info breakpoints。
(gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004005c2 in main at sum.c:11
这里只有一个断点,并且是已启用的。要禁用或启用断点,请指定断点号,使用disable命令。以后要启用,请使用enable命令。
(gdb) disable 1 (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep n 0x00000000004005c2 in main at sum.c:11
您还可以使用delete命令删除断点。
调试运行进程
在GNU/Linux系统中,有许多进程在后台运行。要调试运行中的进程,首先需要找到该特定进程的进程ID。pidof 命令可以给出进程的进程ID。
$ pidof <process_name>
现在我们需要将该进程ID附加到gdb。有两种方式。
1. 通过在gdb中指定进程ID。
$ gdb -p <pid>
2. 使用gdb中的attach命令。
(gdb) attach <pid>
目前就介绍这些。这只是gdb的基础知识,让你轻松开始调试源代码,实际上它比上述内容更加强大。例如,我们可以使用堆栈信息、环境变量等进行调试。尝试使用这些功能玩一下吧…
Source:
https://www.tecmint.com/debug-source-code-in-linux-using-gdb/