Linux 包含了一个叫 gdb 的 GNU 调试程序. gdb 是一个用来调试 C 和 C++ 程序的强 力调试器. 它使你能在程序运行时观察程序的内部结构和内存的使用情况. 以下是 gdb 所提供的一些功能:
- 它使你能监视你程序中变量的值.
- 它使你能设置断点以使程序在指定的代码行上停止执行.
- 它使你能一行行的执行你的代码.
在命令行上键入 gdb 并按回车键就可以运行 gdb 了, 如果一切正常的话, gdb 将被启 动并且你将在屏幕上看到类似的内容:
- [lxiron@FedoraOS myfolder]$ gdb
- GNU gdb (GDB) Fedora (7.1-18.fc13)
- Copyright (C) 2010 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 "i686-redhat-linux-gnu".
- For bug reporting instructions, please see:
- <http://www.gnu.org/software/gdb/bugs/>.
- (gdb)
gdb 基本命令
gdb 支持很多的命令使你能实现不同的功能. 这些命令从简单的文件装入到允许你检查 所调用的堆栈内容的复杂命令, 表27.1列出了你在用 gdb 调试时会用到的一些命令.
命令描述
- file 装入想要调试的可执行文件.
- kill 终止正在调试的程序.
- list 列出产生执行文件的源代码的一部分.
- next 执行一行源代码但不进入函数内部.
- step 执行一行源代码而且进入函数内部.
- run 执行当前被调试的程序
- quit 终止 gdb
- watch 使你能监视一个变量的值而不管它何时被改变.
- print 显示表达式的值
- break 在代码里设置断点, 这将使程序执行到这里时被挂起.
- make 使你能不退出 gdb 就可以重新产生可执行文件.
- shell 使你能不离开 gdb 就执行 LINUX shell 命令.
gdb 支持很多与 UNIX shell 程序一样的命令编辑特征. 你能象在 bash 或 tcsh里那样 按 Tab 键让 gdb 帮你补齐一个唯一的命令, 如果不唯一的话 gdb 会列出所有匹配的命 令. 你也能用光标键上下翻动历史命令.
gdb 应用举例
本节用一个实例教你一步步的用 gdb 调试程序. 被调试的程序相当的简单, 但它展示了 gdb 的典型应用. 我用了一个简单的Hello例子展示了GDB的基本调试功能,先给出源代码:
- include<stdio.h>
- main()
- {
- int a,b,m;
- int max(int a,int b);
- printf("Pls input a,b:/n");
- scanf("%d,%d",&a,&b);
- m=max(a,b);
- printf("Max=%d/n",m);
- }
- int max(int a,int b)
- {
- if(a>b)
- {
- return a;
- }
- else
- {
- return b;
- }
- }
[lxiron@FedoraOS myfolder]$ gcc -g hello.c -o hello ------编译并打开GDB调试选项;
[lxiron@FedoraOS myfolder]$ gdb hello
...... ------这个是GDB版本及相关信息我把它删掉了没有拷贝上来。
(gdb) run -----运行程序
Starting program: /home/lxiron/myfolder/hello
Pls input a,b: ------提示输入两个数
34,15
Max=34
Program exited with code 07.
Missing separate debuginfos, use: debuginfo-install glibc-2.12.1-4.i686
(gdb) list ------我们可以用list命令显示出部分源代码 我用了3次list显示出了全部的源代码
1 #include<stdio.h>
2 main()
3 {
4 int a,b,m;
5 int max(int a,int b);
6 printf("Pls input a,b:/n");
7 scanf("%d,%d",&a,&b);
8 m=max(a,b);
9 printf("Max=%d/n",m);
10 }
(gdb) list ------ 第二次List
11 int max(int a,int b)
12 {
13 if(a>b)
14 {
15 return a;
16 }
17 else
18 {
19 return b;
20 }
(gdb) list ------第三次List
21 }
(gdb) list 9 ------当然我们可以用list加行号显示该行附近的源代码,本程序显示的第九行附近的源代码
4 int a,b,m;
5 int max(int a,int b);
6 printf("Pls input a,b:/n");
7 scanf("%d,%d",&a,&b);
8 m=max(a,b);
9 printf("Max=%d/n",m);
10 }
11 int max(int a,int b)
12 {
13 if(a>b)
(gdb) break 8 ------我们可以用break命令设置断点 该程序我在第8行设置了断点
Breakpoint 1 at 0x8048476: file hello.c, line 8. ------设置断点后的提示信息
(gdb) run ------再次运行程序
Starting program: /home/lxiron/myfolder/hello
Pls input a,b:
45,23
Breakpoint 1, main () at hello.c:8
8 m=max(a,b); ------结果程序运行到了主函数的第8行停了下来
(gdb) watch m ------用watch 命令查看m的值
Hardware watchpoint 2: m
(gdb) next ------用next命令单步执行到第九行
9 printf("Max=%d/n",m);
(gdb) next ------再次使用next打印出执行结果
Max=45
10 }
(gdb) next ------当第三次使用next时则提示程序已经执行结束,跳出程序块。
Watchpoint 2 deleted because the program has left the block
in which its expression is valid.
0x00333cc6 in __libc_start_main () from /lib/libc.so.6
我们修改一下程序,写一个for循环来了解更多的命令,修改后的程序如下,一个for循环:
- #include<stdio.h>
- main()
- {
- int i,sum=0;
- for(i=0;i<10;i++)
- {
- sum+=i;
- }
- printf("sum=%d/n",sum);
- }
[lxiron@FedoraOS myfolder]$ gcc -g hello.c -o hello
[lxiron@FedoraOS myfolder]$ gdb hello
(gdb) list -----用list 显示源程序部分代码
1 #include<stdio.h>
2 main()
3 {
4 int i,sum=0;
5 for(i=0;i<10;i++)
6 {
7 sum+=i;
8 }
9 printf("sum=%d/n",sum);
10 }
(gdb) break 5 ------用break设置断点
Breakpoint 1 at 0x80483d5: file hello.c, line 5.
(gdb) run ------运行程序
Starting program: /home/lxiron/myfolder/hello
Breakpoint 1, main () at hello.c:5
5 for(i=0;i<10;i++) ------执行到断点处,程序停了下来
Missing separate debuginfos, use: debuginfo-install glibc-2.12.1-4.i686
(gdb) step ------step 命令,单步执行,一次执行一句代码
7 sum+=i;
(gdb) print i ------print命令打印出当前变量的值 该行是打印出 i 的值
$1 = 0
(gdb) step
5 for(i=0;i<10;i++)
(gdb) print sum
$2 = 0
(gdb) step
7 sum+=i;
(gdb) print i
$3 = 1
(gdb) step
5 for(i=0;i<10;i++)
(gdb) print sum
$4 = 1
(gdb) step
7 sum+=i;
(gdb) print i
$5 = 2
(gdb) step
5 for(i=0;i<10;i++)
(gdb) print sum
$6 = 3
(gdb) step
7 sum+=i;
(gdb) print i
$7 = 3
(gdb) step
5 for(i=0;i<10;i++)
(gdb) p sum ------p print 命令的简写
$8 = 6
(gdb) s ------s step 命令的简写
7 sum+=i;
(gdb) p i
$9 = 4
(gdb) s
5 for(i=0;i<10;i++)
(gdb) p sum
$10 = 10
(gdb) s
7 sum+=i;
(gdb) p i
$11 = 5
(gdb) s
5 for(i=0;i<10;i++)
(gdb) p sum
$12 = 15
(gdb) s
7 sum+=i;
(gdb) p i
$13 = 6
(gdb) s
5 for(i=0;i<10;i++)
(gdb) p sum
$14 = 21
(gdb) s
7 sum+=i;
(gdb) p i
$15 = 7
(gdb) s
5 for(i=0;i<10;i++)
(gdb) p sum
$16 = 28
(gdb) s
7 sum+=i;
(gdb) p i
$17 = 8
(gdb) s
5 for(i=0;i<10;i++)
(gdb) p sum
$18 = 36
(gdb) s
7 sum+=i;
(gdb) p i
$19 = 9
(gdb) s
5 for(i=0;i<10;i++)
(gdb) p sum
$20 = 45
(gdb) s
9 printf("sum=%d/n",sum);
(gdb) p i
$21 = 10
(gdb) s
sum=45
10 }
(gdb) p sum
$22 = 45
(gdb) s
0x00333cc6 in __libc_start_main () from /lib/libc.so.6
(gdb) kill ------kill 命令,终止正在调试的程序,简写为k;
Kill the program being debugged? (y or n) y
(gdb) quit ------quit命令,退出gdb调试,简写为q;
[lxiron@FedoraOS myfolder]$
好了就写到这里通过上面的调试我们已经感觉到了gdb调试器的功能强大,它可以监视我们程序执行的每一步执行结果,我之前用过visual studio 2005的图形界面调试器,我觉得用熟悉的话两者的调试用能都非常的棒;