mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-02-03 23:40:14 +08:00
PUB:20170116 How to debug C programs in Linux using gdb
@zhb127
This commit is contained in:
parent
668a417504
commit
0cc4f929cf
@ -1,25 +1,19 @@
|
||||
在 Linux 中如何使用 gdb 调试 C 程序
|
||||
============================================================
|
||||
|
||||
### 内容介绍
|
||||
|
||||
1. [GDB 调试器基础][1]
|
||||
2. [GDB 调试器用例][2]
|
||||
3. [总结][3]
|
||||
|
||||
无论多么有经验的程序员,开发的任何软件都不可能完全没有 bug。因此,排查及修复 bug 成为软件开发周期中最重要的任务之一。有许多办法可以排查 bug(测试、代码自审等等),但是还有一些专用软件(称为调试器)可以帮助准确定位问题的所在,以便进行修复。
|
||||
|
||||
如果你是 C/C++ 程序员,或者使用 Fortran 和 Modula-2 编程语言开发软件,那么你将会很乐意知道有这么一款优秀的调试器 -[GDB][4]- 可以帮你更轻松地调试代码 bug 以及其它问题。在这篇文章中,我们将讨论一下 GDB 调试器的基础知识,包括它提供的一些有用的功能/选项。
|
||||
如果你是 C/C++ 程序员,或者使用 Fortran 和 Modula-2 编程语言开发软件,那么你将会很乐意知道有这么一款优秀的调试器 - [GDB][4] - 可以帮你更轻松地调试代码 bug 以及其它问题。在这篇文章中,我们将讨论一下 GDB 调试器的基础知识,包括它提供的一些有用的功能/选项。
|
||||
|
||||
在我们开始之前,值得一提的是,文章中的所有说明和示例都已经在 Ubuntu 14.04LTS 中测试过。教程中的示例代码都是 C 语言写的;使用的 shell 为 bash(4.3.11);GDB 版本为 7.7.1。
|
||||
在我们开始之前,值得一提的是,文章中的所有说明和示例都已经在 Ubuntu 14.04 LTS 中测试过。教程中的示例代码都是 C 语言写的;使用的 shell 为 bash(4.3.11);GDB 版本为 7.7.1。
|
||||
|
||||
### GDB 调试器基础
|
||||
|
||||
通俗的讲,GDB 可以让你看到程序在执行过程时的内部流程,并帮你明确问题的所在。我们将在下一节通过一个有效的示例来讨论 GDB 调试器的用法,但在此之前,我们先来探讨一些之后对你有帮助的基本要点。
|
||||
|
||||
首先,为了能够顺利使用类似 GDB 这样的调试器,你必须以指定的方式编译程序,让编译器产生调试器所需的调试信息。例如,在使用 gcc 编译器(我们将在本教程之后的章节用它来编译 C 程序示例)编译代码的时候,你需要使用 -g 命令行选项。
|
||||
首先,为了能够顺利使用类似 GDB 这样的调试器,你必须以指定的方式编译程序,让编译器产生调试器所需的调试信息。例如,在使用 gcc 编译器(我们将在本教程之后的章节用它来编译 C 程序示例)编译代码的时候,你需要使用 `-g` 命令行选项。
|
||||
|
||||
想要了解 gcc 编译器手册页中关于 -g 命令行选项相关的内容,请看[这里][5]。
|
||||
想要了解 gcc 编译器手册页中关于 `-g` 命令行选项相关的内容,请看[这里][5]。
|
||||
|
||||
下一步,确保在你的系统中已经安装 GDB 调试器。如果没有安装,而且你使用的是基于 Debian 的系统(如 Ubuntu),那么你就可以使用以下命令轻松安装该工具:
|
||||
|
||||
@ -29,15 +23,15 @@ sudo apt-get install gdb
|
||||
|
||||
在其他发行版上的安装方法,请看[这里][6]。
|
||||
|
||||
现在,当你按照上述的方式编译完程序(gcc -g 命令行选项),同时也已经安装好 GDB 调试器,那么你就可以使用以下命令让程序在调试模式中运行:
|
||||
现在,当你按照上述的方式编译完程序(`gcc -g` 命令行选项),同时也已经安装好 GDB 调试器,那么你就可以使用以下命令让程序在调试模式中运行:
|
||||
|
||||
```
|
||||
gdb [prog-executable-name]
|
||||
gdb [可执行程序的名称]
|
||||
```
|
||||
|
||||
这样做会初始化 GDB 调试器,但你的可执行程序此时还不会被启动。在这个时候你就可以定义调试相关的设置。例如,你可以在特定行或函数中设置一个断点让 GDB 暂停程序的执行。
|
||||
这样做会初始化 GDB 调试器,但你的可执行程序此时还不会被启动。在这个时候你就可以定义调试相关的设置。例如,你可以在特定行或函数中设置一个断点让 GDB 在该行暂停程序的执行。
|
||||
|
||||
接着,为了启动你的程序,你必须执行以下 gdb 命令:
|
||||
接着,为了启动你的程序,你必须输入执行以下 gdb 命令:
|
||||
|
||||
```
|
||||
run
|
||||
@ -75,7 +69,7 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
简单说明一下这段代码要做什么事。获取 `val` 数组中每一个值,将其赋值给 `out` 变量,然后将 tot 之前的值与 `0xffffffff/out` 的结果值累加,赋值给 `tot` 变量。
|
||||
简单说明一下这段代码要做什么事。获取 `val` 数组中每一个值,将其赋值给 `out` 变量,然后将 `tot` 之前的值与 `0xffffffff/out` 的结果值累加,赋值给 `tot` 变量。
|
||||
|
||||
这里遇到的问题是,当执行这段代码编译后的可执行程序时,产生以下错误:
|
||||
|
||||
@ -84,7 +78,7 @@ $ ./gdb-test
|
||||
Floating point exception (core dumped)
|
||||
```
|
||||
|
||||
因此,要调试这段代码,第一步是使用 -g 选项编译程序。命令如下:
|
||||
因此,要调试这段代码,第一步是使用 `-g` 选项编译程序。命令如下:
|
||||
|
||||
```
|
||||
gcc -g -Wall gdb-test.c -o gdb-test
|
||||
@ -96,10 +90,10 @@ gcc -g -Wall gdb-test.c -o gdb-test
|
||||
gdb ./gdb-test
|
||||
```
|
||||
|
||||
现在,我刚才得到的错误是 `Floating point exception`,大部分人可能已经知道,这是因为 n % x,当 x 为 0 时导致的错误。所以,考虑到这一点,我在 11 行代码除法运算的位置处添加了一个断点。如下:
|
||||
现在,我刚才得到的错误是 `Floating point exception`,大部分人可能已经知道,这是因为 `n % x`,当 x 为 0 时导致的错误。所以,考虑到这一点,我在 11 行代码除法运算的位置处添加了一个断点。如下:
|
||||
|
||||
```
|
||||
(gdb) **break 11**
|
||||
(gdb) break 11
|
||||
```
|
||||
|
||||
注意 `(gdb)` 是调试器的提示信息,我只输入了 `break 11` 命令。
|
||||
@ -121,8 +115,8 @@ Breakpoint 1, main () at gdb-test.c:11
|
||||
正如你所看到的那样,调试器会显示断点所在的行代码。现在,让我们打印出此时 `out` 的值。如下:
|
||||
|
||||
```
|
||||
(gdb)** print out**
|
||||
**$1 = 5**
|
||||
(gdb) print out
|
||||
$1 = 5
|
||||
(gdb)
|
||||
```
|
||||
|
||||
@ -132,7 +126,7 @@ Breakpoint 1, main () at gdb-test.c:11
|
||||
c
|
||||
```
|
||||
|
||||
重复上述操作,直到 `out` 值变为 0 时。
|
||||
重复上述操作,直到 `out` 值变为 `0` 时。
|
||||
|
||||
```
|
||||
...
|
||||
@ -164,7 +158,7 @@ Program received signal SIGFPE, Arithmetic exception.
|
||||
11 tot = tot + 0xffffffff/out;
|
||||
```
|
||||
|
||||
是的,如上高亮输出的内容所示,这就是抛出异常的地方。当我再次尝试运行 `s` 命令时,问题最终也得到了确认:
|
||||
是的,如上输出的第一行内容所示,这就是抛出异常的地方。当我再次尝试运行 `s` 命令时,问题最终也得到了确认:
|
||||
|
||||
```
|
||||
(gdb) s
|
||||
@ -177,7 +171,7 @@ The program no longer exists.
|
||||
|
||||
### 总结
|
||||
|
||||
GDB 提供了很多功能供用户研究和使用,在这里,我们仅仅只介绍了很少一部分内容。通过 GDB 的手册页进一步了解这个工具,当你在调试代码的时候,尝试使用一下它。GDB 调试器有一定的学习难度,但是它很值得你下功夫学习。
|
||||
GDB 提供了很多功能供用户研究和使用,在这里,我们仅仅只介绍了很少一部分内容。通过 GDB 的手册页可以进一步了解这个工具,当你在调试代码的时候,尝试使用一下它。GDB 调试器有一定的学习难度,但是它很值得你下功夫学习。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
Loading…
Reference in New Issue
Block a user