我是靠谱客的博主 愤怒嚓茶,最近开发中收集的这篇文章主要介绍使用GDB调试程序使用GDB调试程序,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

使用GDB调试程序


在Linux下常常需要调试自己的程序,通常使用GDB这个工具来帮助。

[test1280@localhost gdbtest]$ uname -a
Linux localhost.localdomain 2.6.32-431.el6.i686 #1 SMP Fri Nov 22 00:26:36 UTC 2013 i686 i686 i386 GNU/Linux
[test1280@localhost gdbtest]$ which gdb
/usr/bin/gdb
[test1280@localhost gdbtest]$ 

先看下一个简单的C程序:

#include <stdio.h>
#include <stdlib.h>
void print_array(int *parr, int n)
{
int i;
for (i=0; i<n; i++)
{
printf("%d ", parr[i]);
}
printf("n");
}
int main()
{
int arr[5] = {9, 1, 5, 3, 7};
int val = 11;
arr[4] = val;
print_array(arr, 5);
return 0;
}

GDB调试命令:

file   加载被调试的可执行程序文件。
r (run)运行被调试的程序。如果有断点,则将停止在第一个断点处;如果没有断点,则将整个程序运行完。
c (continue)继续执行被调试的程序,直到下一个断点或者程序结束。
b (break)设置断点,后面可以加函数名称或者是行号。
d (delete)删除断点。
s (step)执行下一行源代码,如果有函数调用则进入被调用函数内部。
n (next)执行下一行源代码,即使此行中包含了一个函数调用,也一并执行,并不会进入被调用函数内部。
p (print)打印指定变量的值。
i (info)用于显示各类信息。
q (quit)退出GDB调试交互环境。
help   帮助信息。

[test1280@localhost gdbtest]$ gcc -o main main.c
[test1280@localhost gdbtest]$ gdb
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6)
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) file main
Reading symbols from /home/test1280/gdbtest/main...(no debugging symbols found)...done.
(gdb)

再进行编译链接时没有指定-g参数,那么使用gdb调试会产生:no debugging symbols found的提示;

在编译时指定-g选项:

[test1280@localhost gdbtest]$ gcc -o main main.c -g
[test1280@localhost gdbtest]$ gdb
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6)
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) file main
Reading symbols from /home/test1280/gdbtest/main...done.
(gdb)

现在开始调试:

上面已经使用了第一个命令file,用来加载对应的可执行程序文件。

file  file_name;

(gdb) file main
Reading symbols from /home/test1280/gdbtest/main...done.
(gdb) run
Starting program: /home/test1280/gdbtest/main
9 1 5 3 11
Program exited normally.

由于我们没有设置断点,那么执行run时,将把整个程序都执行。

注:所有的命令简写与完全的都是等价的,即:r等价于run,i等价于info……

(gdb) file main
Reading symbols from /home/test1280/gdbtest/main...done.
(gdb) break main
Breakpoint 1 at 0x8048442: file main.c, line 16.
(gdb) b 4
Breakpoint 2 at 0x80483fa: file main.c, line 4.
(gdb) r
Starting program: /home/test1280/gdbtest/main
Breakpoint 1, main () at main.c:16
16
int arr[5] = {9, 1, 5, 3, 7};
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
(gdb) c
Continuing.
Breakpoint 2, print_array (parr=0xbffff708, n=5) at main.c:7
7
for (i=0; i<n; i++)
(gdb) c
Continuing.
9 1 5 3 11
Program exited normally.
(gdb)

break main指明在main函数处设置断点;
b 4指明在源文件第4行设置断点;

设置完断点后,使用r开始执行,可以看到在main处停止,

16 int arr[5] = {9, 1, 5, 3, 7};

代表的是下一行是这行源代码。

然后使用c(continue命令),继续执行程序,直到下一个断点,也就是第四行。

在第四行使用c,继续执行程序,由于没有断点,则直接将整个程序都执行完了。

(gdb) file main
Reading symbols from /home/test1280/gdbtest/main...done.
(gdb) b 19
Breakpoint 1 at 0x804847a: file main.c, line 19.
(gdb) i b
Num
Type
Disp Enb Address
What
1
breakpoint
keep y
0x0804847a in main at main.c:19
(gdb) info b
Num
Type
Disp Enb Address
What
1
breakpoint
keep y
0x0804847a in main at main.c:19
(gdb) i break
Num
Type
Disp Enb Address
What
1
breakpoint
keep y
0x0804847a in main at main.c:19
(gdb) info break
Num
Type
Disp Enb Address
What
1
breakpoint
keep y
0x0804847a in main at main.c:19
(gdb) r
Starting program: /home/test1280/gdbtest/main
Breakpoint 1, main () at main.c:19
19
print_array(arr, 5);
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
(gdb) s
print_array (parr=0xbffff708, n=5) at main.c:7
7
for (i=0; i<n; i++)
(gdb) s
9
printf("%d ", parr[i]);
(gdb)

使用s可以看到进入了被调用函数内部。

(gdb) file main
Reading symbols from /home/test1280/gdbtest/main...done.
(gdb) b 19
Breakpoint 1 at 0x804847a: file main.c, line 19.
(gdb) i b
Num
Type
Disp Enb Address
What
1
breakpoint
keep y
0x0804847a in main at main.c:19
(gdb) r
Starting program: /home/test1280/gdbtest/main
Breakpoint 1, main () at main.c:19
19
print_array(arr, 5);
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
(gdb) n
9 1 5 3 11
20
return 0;
(gdb) n
21	}
(gdb) n
0x00aa2d26 in __libc_start_main () from /lib/libc.so.6
(gdb) n
Single stepping until exit from function __libc_start_main,
which has no line number information.
Program exited normally.
(gdb)

使用n可以看到,即使在断点处存在函数调用,也会一并执行,区别于s(step)命令。

(gdb) file main
Reading symbols from /home/test1280/gdbtest/main...done.
(gdb) b 19
Breakpoint 1 at 0x804847a: file main.c, line 19.
(gdb) info break
Num
Type
Disp Enb Address
What
1
breakpoint
keep y
0x0804847a in main at main.c:19
(gdb) b print_array
Breakpoint 2 at 0x80483fa: file main.c, line 7.
(gdb) info break
Num
Type
Disp Enb Address
What
1
breakpoint
keep y
0x0804847a in main at main.c:19
2
breakpoint
keep y
0x080483fa in print_array at main.c:7
(gdb) delete 1
(gdb) i b
Num
Type
Disp Enb Address
What
2
breakpoint
keep y
0x080483fa in print_array at main.c:7
(gdb)

使用info break(i b)可以显示断点信息,使用delete 编号可以删除对应的断点。

(gdb) file main
Reading symbols from /home/test1280/gdbtest/main...done.
(gdb) b print_array
Breakpoint 1 at 0x80483fa: file main.c, line 7.
(gdb) r
Starting program: /home/test1280/gdbtest/main
Breakpoint 1, print_array (parr=0xbffff708, n=5) at main.c:7
7
for (i=0; i<n; i++)
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
(gdb) n
9
printf("%d ", parr[i]);
(gdb) n
7
for (i=0; i<n; i++)
(gdb) n
9
printf("%d ", parr[i]);
(gdb) print i
$1 = 1
(gdb) print parr[i]
$2 = 1
(gdb) n
7
for (i=0; i<n; i++)
(gdb) n
9
printf("%d ", parr[i]);
(gdb) n
7
for (i=0; i<n; i++)
(gdb) n
9
printf("%d ", parr[i]);
(gdb) n
7
for (i=0; i<n; i++)
(gdb) n
9
printf("%d ", parr[i]);
(gdb) n
7
for (i=0; i<n; i++)
(gdb) n
11
printf("n");
(gdb) n
9 1 5 3 11
12	}
(gdb) 

上面的执行过程可以看到执行了printf但是并没有输出,这是为什么呢?

我个人认为这个是由于“行缓冲”的关系,直到遇到换行符才ffluash下。

(gdb) file main
Reading symbols from /home/test1280/gdbtest/main...done.
(gdb) b print_array
Breakpoint 1 at 0x80483fa: file main.c, line 7.
(gdb) r
Starting program: /home/test1280/gdbtest/main
Breakpoint 1, print_array (parr=0xbffff708, n=5) at main.c:7
7
for (i=0; i<n; i++)
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
(gdb) n
9
printf("%d ", parr[i]);
(gdb) n
7
for (i=0; i<n; i++)
(gdb) b 11
Breakpoint 2 at 0x804842b: file main.c, line 11.
(gdb) info b
Num
Type
Disp Enb Address
What
1
breakpoint
keep y
0x080483fa in print_array at main.c:7
breakpoint already hit 1 time
2
breakpoint
keep y
0x0804842b in print_array at main.c:11
(gdb) c
Continuing.
Breakpoint 2, print_array (parr=0xbffff708, n=5) at main.c:11
11
printf("n");
(gdb) n
9 1 5 3 11
12	}
(gdb) q
A debugging session is active.
Inferior 1 [process 2901] will be killed.
Quit anyway? (y or n) y
[test1280@localhost gdbtest]$ 

当在一个循环中时,可以设置一个在外部的断点,然后使用c执行,可以跳出这个循环。

(gdb) file main
Reading symbols from /home/test1280/gdbtest/main...done.
(gdb) help
List of classes of commands:
aliases -- Aliases of other commands
breakpoints -- Making program stop at certain points
data -- Examining data
files -- Specifying and examining files
internals -- Maintenance commands
obscure -- Obscure features
running -- Running the program
stack -- Examining the stack
status -- Status inquiries
support -- Support facilities
tracepoints -- Tracing of program execution without stopping the program
user-defined -- User-defined commands
Type "help" followed by a class name for a list of commands in that class.
Type "help all" for the list of all commands.
Type "help" followed by command name for full documentation.
Type "apropos word" to search for commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb) help info
Generic command for showing things about the program being debugged.
List of info subcommands:
info address -- Describe where symbol SYM is stored
info all-registers -- List of all registers and their contents
info args -- Argument variables of current stack frame
info auto-load -- Print current status of auto-loaded files
info auto-load-scripts -- Print the list of automatically loaded Python scripts
info auxv -- Display the inferior's auxiliary vector
info bookmarks -- Status of user-settable bookmarks
info breakpoints -- Status of user-settable breakpoints
info catch -- Exceptions that can be caught in the current stack frame
info checkpoints -- IDs of currently known checkpoints
info classes -- All Objective-C classes
info common -- Print out the values contained in a Fortran COMMON block
info copying -- Conditions for redistributing copies of GDB
info dcache -- Print information on the dcache performance
info display -- Expressions to display when program stops
info extensions -- All filename extensions associated with a source language
info files -- Names of targets and files being debugged
info float -- Print the status of the floating point unit
info frame -- All about selected stack frame
info functions -- All function names
info handle -- What debugger does when program gets various signals
info inferiors -- IDs of currently known inferiors
---Type <return> to continue, or q <return> to quit---q
Quit
(gdb) q
[test1280@localhost gdbtest]$

可以单独使用help命令,也可以使用help来具体显示某一个命令。

以上仅仅是GDB的最简单的功能,后续会继续介绍GDB更加强大的功能。

最后

以上就是愤怒嚓茶为你收集整理的使用GDB调试程序使用GDB调试程序的全部内容,希望文章能够帮你解决使用GDB调试程序使用GDB调试程序所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部