说明:部分摘抄自《零点起飞学 Linux C》
安装GDB
Ubuntu等基于Debian的linux: apt-get install gdb
Fedora等基于RPM的linux:yum install gdb
使用GDB
- 启动/退出GDB
$gdb
退出quit (简写为q)
- 载入程序
gdb example
或file example
- 列出源码
list (简写为l)
如(gdb)l 3,5 列出3~5行代码
- 执行程序
(gdb)run or r
- 使用帮助功能
(gdb)help
or(gdb)help run(具体命令)
设置断点与管理断点
- 设置断点:
(gdb)break 9
or(gdb)b 9
在第9行设置断点- 继续运行程序
(gdb)continue or c
- break命令后也可以跟函数名,使程序在进入指定的函数之前停下来。设置断点也可以进行条件判断,即只有条件为真、程序到达指定行或函数时停下来。
(gdb)b 9 if i>9
- 查看断点信息:
(gdb)info break
- 删除断点:
(gdb)delete 1 or d 1
删除编号为1的断点(gdb)d 1-6
删除编号为1-6的断点
- 删除指定行上的断点:
(gdb)clear 9
- 禁用指定的断点
(gdb)disable 1
用(gdb)info break
查看断点信息 - 设置观察点
(gdb)watch tol
观察变量tol ,必须在断点后设置观察点,run后才能设置。 - 当变量或表达式的值发生变化时,暂停程序的运行,如果想在变量或表达式被读时暂停程序的运行,可以使用rwatch命令;如果想在变量或表达式被读或被写时暂停程序的运行,可以使用awatch命令。
info watchpoints
查看当前所有观察点,可以用delete命令删除指定的观察点。
显示数据与改变量值
显示数据用于查看数据在程序运行过程中的值。改变变量值是在程序调试过程中,可以修改变量的值,以方便发现错误。
- 显示变量或表达式的值:
(gdb)print (or p)tol
- 指定格式:
(gdb)p/x tol
以十六进制格式显示 - t:二进制 o (八进制)d(十进制)c(字符格式) f(浮点数)
print 命令可以显示数组内容、函数调用等信息。(gdb) p *a@6
*a为数组的地址,6为数组的长度。查看a数组各元素的值 自动显示变量或表达式的值
(gdb) display tol
每次运行到断点处都会自动显示变量tol的值。(gdb) info display
undisplay 或delete display
disable display
enable display
通过whatis或ptype命令来查看变量的数据类型
(gdb) whatis a
(gdb) ptype tol
修改变量的值
(gdb) set tol=100
执行命令和调试函数
单步调试:
单步执行就是一步一步跟踪程序执行的流程,根据变量的值,找到错误的原因。
step(简写为s)
可以跟踪进入函数内部,在执行到函数调用部分时,GDB会给出提示信息,包括被调函数的入口参数、起始行号等。同时也会给出函数中将要执行的语句及所在行的号。
next(简写为n)
不进入函数,将函数调用看做是一条语句,不跟踪进入函数内部。
s进入函数后,return 和finish
命令退出被调用的函数。
执行到指定行 :(gdb) until 行号
跳转执行:(gdb) jump 行号
强制调用函数:call printf("End\n")
查看堆栈信息
程序运行中调用函数时,函数的首地址、参数、以及函数内的局部变量等都会被压入程序栈内。
backtrace(简写为bt)和frame(简写为f)
命令查看栈的信息。
(gdb) f 1 1
为栈帧的编号
查看当前栈帧的详细信息,info frame 或(info f)
查看源程序信息:(gdb) info source
查看寄存器:info registers
(不包括浮点寄存器)
info all-registers
(包括浮点寄存器)
(gdb)p $eip
访问单个寄存器,在寄存器前面加$
查看程序的汇编代码:在调试程序过程中,可以通过disassemble命令来显示程序的汇编代码! disassemble printinfo
在linux平台下GDB是一款强大的调试工具。
GDB主要帮你完成以下四个方面的功能:
1、 启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
2、 可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
3、 当程序被停住时,可以检查此时你的程序中所发生的事。
4、 动态的改变你程序的执行环境。
一般来说GDB主要调试的是C/C++的程序。
调试信息(-g)
要调试C/C++的程序,首先在编译时,我们必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的 -g 参数可以做到这一点。
如:
> cc -g hello.c -o hello
> g++ -g hello.cpp -o hello
如果没有-g,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址。当你用-g把调试信息加入之后,并成功编译目标代码以后,让我们来看看如何用gdb来调试他。
启动GDB的方法有以下几种:
1、gdb "program"
program也就是你的执行文件,一般在当前目录下。
2、gdb "program” core
用gdb同时调试一个运行程序和core文件,core是程序非法执行后core dump后产生的文件。
3、gdb program PID
如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程ID。gdb会自动attach上去,并调试他。program应该在PATH环境变量中搜索得到。
在启动了gdb后,就可以开始使用gdb中命令了。如果希望查看都有哪些命令,可以输入help进行查询。
下面简单演示几个小例子:
示例一:在进入函数func时,设置一个断点。可以敲入break func,或是直接就是b func
(gdb) b func
Breakpoint 1 at 0x8048458: file hello.c, line 10.
示例二:敲入b按两次TAB键,你会看到所有b打头的命令:
(gdb) b
backtrace break bt
示例三:调试C++的程序时,有可能函数名一样。如:
(gdb) b 'bubble( M-?
bubble(double,double) bubble(int,int)
(gdb) b 'bubble(
你可以查看到C++中的所有的重载函数及参数。(注:M-?和“按两次TAB键”是一个意思)
需要特别说明的是,在gdb中运行程序时,使用run命令,可能需要做以下的操作。
- 程序运行参数。
set args
可指定运行时参数。(如:set args 10 20 30 40 50)
show args
命令可以查看设置好的运行参数。 - 运行环境。
path “dir” 可设定程序的运行路径。
show paths 查看程序的运行路径。
set environment varname [=value] 设置环境变量。如:set env USER=hchen
show environment [varname] 查看环境变量。 - 工作目录。
cd “dir” 相当于shell的cd命令。
pwd 显示当前的所在目录。 - 程序的输入输出。
info terminal 显示你程序用到的终端的模式。
使用重定向控制程序输出。如:run > outfile
tty命令可以指写输入输出的终端设备。如:tty /dev/ttyb
gdb可以对多个线程设置断点
gdb 可以打印栈信息
下面是我借鉴的几个网址:
GDB十分钟教程 (讲了一些最常用的参数,和一个简单练习。入门很不错,我以前就是按这学习的)
陈皓的GDB调试程序(讲得挺详细的,提到了好多功能,不看不知道,如果能把GDB运用好,那会节省多少工作量)
gcc/g++在执行编译工作的时候,总共需要以下几步:
1.预处理,生成.i的文件[预处理器cpp]
2.将预处理后的文件转换成汇编语言,生成文件.s[编译器egcs]
3.有汇编变为目标代码(机器代码)生成.o的文件[汇编器as]
4.连接目标代码,生成可执行程序[链接器ld]
GCC 常用命令行:
我常用一句:gcc -Wall -g example.c -o example
-Wall 启动所有警告消息
-g 获取有关调试程序的详细信息。
(注意:不能和优化选项一起使用,因为在对代码进行优化的过程中,某些代码可能被改写,或为了取得最佳的性能而进行了重组,这样对程序的跟踪和调试时非常不利的。)
总结:
只是看了一下他们有哪些功能。不怕不熟练,就怕不知道。我们有时候费很大力气搞出来的东西,其实工具自身已经自带这个功能,一个参数搞定~~~对GCC和GDB的有些功能暂时还没有用到,所以体会不是很深。