GDB让调试变简单

       gdb(GNU Debugger)它是GNU组织发布的程序调试工具,在UNIX和类UNIX操作系统上都可使用GDB,目前GDB所能支持的编程语言有C,C++,JAVA等语言,主要用于调试C/C++.gdb以纯文本命令行执行,操作者熟悉以后可以利于它方便的调试程序,把程序的BUG找出来,同时它适用于子进程,多线程的调试.

编译选项

在程序源代码进行编译的时候,gcc的选项必须加上-g把调试信息加入到可执行文件中去,这样才可以通过gdb对程序进行调试查错.如:

> gcc -g hello.c -o hello

-g选项的作用是在可执行文件中加入源代码的信息,比如可执行文件中第几条机器指令对应源代码的第几行,但并不是把整个源文件嵌入到可执行文件中,所以在调试时必须保证gdb能找到源文件。如果源代码文件不在也是无法对应到源代码的,无法的清晰的对应到程序.另外如果不加入-g,你将看不见程式的函数名、变量名,所代替的全是运行时的内存地址。

gdb的启动

1.>gdb <程序名>

2.>gdb <程序名> <core File>   (或者>gdb <进程名> –c <core file>)

3.>gdb <程序名> <pid>      (或者>gdb –p <pid>)       (或者>gdb attach <pid>)

常见指令

单步调试指令

Start

启动进程

next(n)

单步运行程序-不进入函数

step(s)

单步运行程序-进入函数体

空格

重复上次指令

断点调试指令

run(r)

运行进程

continue(c)

继续运行

break(b) 行号

在指定行号设置断点

break(b) 函数名

在进入函数前断点停止

break(b) 文件名:行名/函数名

指定某个文件的断点,

break(b) 行号 if <condition>

当条件满足时,在某处发生断点

info break

列出当前断点

delete break [n]

删除指令的断点

clear

清除断点

quit(q)

退出gdb

调试信息输出

list(l)

列出源代码

backtrace

显示所有的调用栈桢

up

上移栈桢

down

下移栈桢

info stack

显示所有的调用栈桢

info locals

显示函数中的局部变量

whatis <变量名>

显示指定变量的类型

print(p) <变量名>

打印变量值

x

打印内存内容

x/16bx &aa

从变量aa的内存地址开始读取16字节的内容,16b:16字节,x以16进制显示。

x/3hu 0x8054320

从内存地址0x8054320读取内容,3h显示3个[双字节]内容,u表示按无符号显示。默认为10进制

where

查看进程运行到哪里了

display/undisplay [变量名]

断点发生时,同时显示变量的值./关闭跟踪显示

set variable <变量>=<值>

设置变量的值进行调试

help

帮助

线程指令

info thread

列出进程的所有线程

thread [n]

进入指定线程

 

 

设置

set follow-fork-mode child

进程直接进入子进程

 

 

段错误快速发现

段错误通常发生在内存溢出,非法访问造成,在我们平时程序中经常出现的问题,对问题的发现和跟踪也是非常的麻烦,这里我们通常gdb来快速发现段错误的发生地.

如下进程发现了段错误,如果通过printf去逐行调试是比较麻烦.

[root@host70-151 kernel]# ./gdb_core

段错误

通过gdb来运行,就为我们提供调试程序提供了更的帮助信息.

         [root@host70-151 kernel]# gdb ./gdb_core

Program received signal SIGSEGV, Segmentation fault.

main () at kernel/gdb_core.c:9

9              p[6] = 'B';

(gdb)

进程阻塞查询(实战)

联通网关SGIP进程经常出现不工作情况,对它进行调试,首先netstat或者lsof查看当前的网络连接是否还在.发现进程一切进程,如此初步判断进程应该是出现了阻塞.下面使用gdb进入进程调试:

>gdb -p <pid>

(gdb) info stack    /*打印所有的栈桢*/

#0  0x001d92e6 in recv () from /lib/i686/libc.so.6

#1  0x0805d555 in CSocket::Receive (this=0xbffff7a8, p_pchBuf=0xbfffed40 "", p_iLen=1024, p_iFlag=0) at lib/Socket.cpp:431

#2  0x0804fccb in SGIPInterface::UnBindSMG (this=0xbffff770) at lib/SGIPInterface.cpp:493

#3  0x08050b05 in SGIPInterface::Start (this=0xbffff770) at lib/SGIPInterface.cpp:617

#4  0x0804ab9e in main () at kernel/SGIPClient.cpp:32

  发现进程在调用recv的时候出现阻塞,同时它是UnBindSMG的时候.进入相应代码进行修改.

gdb调试core异常退出

在程序还进入稳定期,进程会在少数情况下出现异常,这种异常情况通常很难模拟,程序的问题也很发现,而且进程还会退出去,这种情况下就是程序员非常头痛的事情.下面我们提出一个core文件的解决办法.

core dump设置

         Linux默认情况下是关键了core文件的生成,我们需要将它打开.我们首先通过ulimit观察core的状态.  

[root@host70-151 kernel]# ulimit -a

core file size         (blocks, -c) 0

这里需要注意的是它的单位是blocks,一个block在磁盘对应一个扇区,每个扇区大小为512字节.如果我们要设置core大小5K,那么如下操作

[root@host70-151 kernel]# ulimit -c 10

core文件调试

gdb <程序名> <core文件名>

         注意这里调试的时候一定要加上的程序名,而不只是加上core文件名.下面这个例子会生成core文件,core文件名通常为core.<pid>,如core.19203,后面跟着进程号.

/*

 * file name: gdb_core.c

 */ 

#include "inc.h"

static void fun()

{

        unsigned char *p; 

        p = 0x8048000;

        p[6] = 'B';

       printf("%s\n", p);

}

int main()

{

       printf("%d\n", getpid());

        fun();

        return 0;

}

运行上面程序会直接退出,同时生成core文件.现在我们对它进行调试,找出问题所在:

[root@host70-151 kernel]# gdb gdb_core core.1670

Core was generated by `./gdb_core'.

Program terminated with signal 11, Segmentation fault.

[New process 1670]

#0  main () at kernel/gdb_core.c:9

9               unsigned char *p;

(gdb) where

#0  main () at kernel/gdb_core.c:9

(gdb) bt

#0  main () at kernel/gdb_core.c:9

如上可以发现进程发生段错误,系统给出了11号信号.程序最后的执行到了第9行.

其他

gdb还可以远程调试android可以查阅相关资料。

Linux下面还可以配合跟踪工具配合调试,如:strace mtrace ltrace

strace –f 进程 : -f 跟踪由fork调用所产生的子进程. 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值