GNU调试器或GDB:用于Linux程序的强大源代码调试工具

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.

Debugging source code with GNU Debugger

GNU Debugger,又称为gdb,允许我们在代码执行时查看代码或在程序崩溃前程序尝试做什么。 GDB 基本上帮助我们完成四件主要事情以捕捉源代码中的缺陷。

  1. 启动程序,指定可能影响一般行为的参数。
  2. 在指定条件下停止程序。
  3. 检查崩溃或程序停止时的情况。
  4. 更改代码并立即尝试修改后的代码。

我们可以使用 gdb 轻松调试用C和 C++ 编写的程序。目前对于其他编程语言如DModula-2Fortran 的支持是部分的。

开始学习 GNU Debugger 或 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

請注意兩個指令stepnext之間的差異。指令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 = 1b = 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

這裡只有一個斷點,它是To。要禁用斷點,請指定斷點編號並使用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. 通過將進程ID與gdb一起指定。

$ gdb -p <pid>

2. 使用gdb中的attach命令。

(gdb) attach <pid>

目前就這些。這些僅是gdb的基礎知識,可幫助您從源代碼調試方面良好開始,而實際上,gdb提供的功能遠不止以上所述的內容。例如,我們可以使用堆棧信息、環境變量等進行調試。請嘗試玩弄所有這些東西…

Source:
https://www.tecmint.com/debug-source-code-in-linux-using-gdb/