如何gdb调试一个运行中的进程

 我来答
samhan
2016-11-05 · 知道合伙人互联网行家
samhan
知道合伙人互联网行家
采纳数:10996 获赞数:56045
对待工作认真负责,善于沟通、协调有较强的组织能力与团队精神。

向TA提问 私信TA
展开全部
第一步 编译一个死循环程序。

/* File name malloc.c*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void getmem(void **p, int num){
*p = (void *)malloc(num);
}

void test(void){
char *str = NULL;
getmem((void **)&str, 100);
strcpy(str, "Hello");
printf("%s\n", str);
}

int main(void){
int i = 0;
while(1){
if (i == 1){
test();
return 1;
}
}
return 0;
}

我们可以看出,这个程序就是malloc一段内存空间,用来供strcpy使用,由于只是调试一下,就没有在test程序中加上一些关于strcpy的正确性判断语句。
函数的正常退出的情况是i==1,但是程序运行过程中根本无法使i==1成立。i的变量的值将会在使用gdb时用到。

开始编译
$gcc -g malloc.c

得用gdb,加上-g还是需要的。生成的可执行文件为a.out

第二步 让gdb连接到正在执行的进程上去
首先运行程序。
$./a.out
明显的,是一个死循环。

重新开一个shell
$ps -u
我的机器的运行情况如下所示:
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
wyc 7712 0.0 0.1 6092 3644 pts/8 Ss 10:24 0:00 bash
wyc 7880 0.0 0.1 6092 3608 pts/9 Ss 10:27 0:00 bash
wyc 7929 0.0 0.3 10848 6468 pts/9 S+ 10:28 0:00 gdb
wyc 8347 93.0 0.0 1652 284 pts/8 R+ 10:42 0:13 ./a.out
...

看到没有? ./a.out的进程号是8347。

现在启动gdb
$gdb

由于是调试运行的进程,不是可执行文件,后面不需要跟任何参数。在用 gdb调试运行状态下的程序时,最核心的就是gdb内部的attach命令
用法为
(gdb) attach

这是我的机器上的例子:
$ gdb
GNU gdb (GDB) 7.1.50.20100621
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
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-pc-linux-gnu".
For bug reporting instructions, please see:
.
(gdb) attach 8347
Attaching to process 8347
Reading symbols from /home/wyc/desktop/my_program/review/a.out...done.
Reading symbols from /lib/tls/i686/cmov/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/tls/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
main () at malloc.c:19
19 if (i == 1){
(gdb) p i
$1 = 0
(gdb) set i=1
Ambiguous set command "i=1": .
(gdb) i=1
Undefined info command: "=1". Try "help info".
(gdb) set i=1
Ambiguous set command "i=1": .
(gdb) set var i=1
(gdb) l
14 }
15
16 int main(void){
17 int i = 0;
18 while(1){
19 if (i == 1){
20 test();
21 return 1;
22 }
23 }
(gdb) n
20 test();
(gdb)
21 return 1;
(gdb)
25 }
(gdb)
0xb7f47775 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
(gdb)
Single stepping until exit from function __libc_start_main,
which has no line number information.

Program exited with code 01.
(gdb)

在运行到第20行命令的时候,可以看一下到运行./a.out的那个shell,应该hello字符串在标准输出上了。当gdb中显示进程退出时,./a.out的shell应该结束了当前进程了。
在gdb中用set var i=1 来修改变量i的值(用set i=1不能识别命令),使程序能够正常退出。

在调试时,当前程序调用的所有库也全部都出来了。这个例子中的
Reading symbols from /home/wyc/desktop/my_program/review/a.out...done.
Reading symbols from /lib/tls/i686/cmov/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/tls/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
是a.out程序所调用的全部库。可以用这种办法分析当前运行的程序的库的调用情况。

千万不要关掉gdb,以下调试更精彩:

第三步 在gdb中重启程序
在上面已经知道了程序正常退出了,但是gdb还没有退出,这时在gdb中运行run效果如何?

(gdb) run
Starting program: /home/wyc/desktop/my_program/review/a.out
下面是死循环了...
接下Ctrl+c,给gdb发个SIGINT的信号。

^C
Program received signal SIGINT, Interrupt.
main () at malloc.c:19
19 if (i == 1){
(gdb) p i
$2 = 0
(gdb) set var i=1
(gdb) n
20 test();
(gdb) n
Hello
21 return 1;
(gdb) n
25 }
(gdb) n
0xb7e7b775 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
(gdb) n
Single stepping until exit from function __libc_start_main,
which has no line number information.

Program exited with code 01.

可以看出,用gdb连接进程后,他会找到运行这个进程所需的全部文件,当前进程关闭后,仍然可以在gdb中启动这个程序。

不得不佩服GDB的调试功能的强大

gdb中的其它命令,就看你分析程序时是否用到了,例如下面的一些简单的命令:

常用的bt, p , p/x , setp, info registers, break , jump ......
临危不俱strong
2016-11-05 · TA获得超过133个赞
知道答主
回答量:109
采纳率:0%
帮助的人:72.3万
展开全部
例如程序的可执行文件名称为Dome
gdb Dome

进入gdb对话框。你要调试程序的某一段代码,在进入那段代码前打上一个断点。
break filename:linenum

然后执行程序
run
此时程序开始运行,如果是GUI界面,你可以在界面进行操作,当这些操作调用断点后的代码时,程序会停下来,这是你可以输入命令进行调试了,
next 2 //执行下面两行代码
本回答被网友采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式