Linux C程序设计大全之gdb学习
1,列出源程序
1.1 不带参数的list命令
list命令首次使用显示main函数之前的或之后的10行内容,之后会显示上次内容或之后的10行内容。
1.2 带参数的list命令
list <line-number>显示参数之前或者之后总共10行内容
1.3 带两个参数的list命令
list<line1,line2>显示从line1到line2的所有内容
2, 运行程序的命令
当需要在gdb中运行准备调试的程序。可使用run命令。在它后面可以跟发给程序的任何参数,包括输入输出重定向(<和>)和shell通配符(*,?,[,])在内。其命令格式如下
(gdb) run <arg1 arg2…>
(gdb) show args
显示运行程序时传入的参数
(gdb) set args chg1 chg2
将传入的参数设置为chg1 chg2
3, 操作断点的命令
3.1 设置断点
3.1.1 在源程序中指定的行上设置断点
break <line-number>在源程序指定行中指定的行上设置断点,使程序执行到设置断点的行之前停止。
这种用法通常使用list和break来获得断点的行数。
3.1.2 在指定的函数前设置断点
break <function-name>
break printstar 在源程序调用函数printstar()前设置一个断点,所以使用break
3.1.3 使用表达式设置断点
break <line number> if<conditional expression>
(gdb) break 12 if i==9
(gdb) run
(gdb) info locals
需要注意,在条件中指定的变量必须在设置断点的行的变量作用域内,否则,这个表达式就没有意义。如果一个断点例如,1号断定已经在19行定义好了,则可以使用condition命令在这个断点上设置条件,如下所示:
(gdb) condition 1 if i==30
也可以使用condition命令指定断点,但是不加表达式从而使这个断点成为非条件型表达式如下:
(gdb) condtion 1
(gdb) info break
查看断点信息.
3.1.4 在指定例程的入口处设置断点
如果程序由很多源文件构成的,则可以在各个源文件中设置断点,命令格式如下:
break <filename:line-number> break<filename:function-name>
(gdb) break temp.c:10
(gdb) break temp.c:main
3.2 显示当前gdb的断点信息
info break
3.3 删除指定的断点
delete breakpoint <point-number>
(gdb) delete breakpoint 1
注意这里的breakpoint 不是行数,而是断点的标号
3.4 禁止或启用断点
enable和disable命令用来设置断点的可用属性,但是禁用并不代表深处断点,使用info break命令依然可以看到断点信息。
enable breakpoint <point-number>
(gdb) enable breakpoint 1
disable breakpoint <point-number>
(gdb) disable breakpoint 1
3.5 清除断点
clear的功能是清除源文件中某一代码行上的所有断点。
3.5.1 不带参数的clear命令
(gdb) break 19
(gdb) r
(gdb) clear
运行程序在第19行停止,使用clear清除停止出的断点。
3.5.2 带参数的clear命令
clear <number>
(gdb) break 20
(gdb) break 20
(gdb) clear 20
删除第20行上的所有的断点
3.6 观察点
watch命令在程序中设置一个观察点(即数据断点)。命令格式如下:
watch <condition> condition是触发观察点的条件,一旦触发会导致gdb中断。
4, 查看运行时数据
4.1 数据观察命令
利用print命令可以检查各个变量的值。命令格式如下:
print <varable-name>
<gdb> print a 如果局部变量和全局变量发生冲突(也就是重名),一般情况下是局部变量会隐藏全局变量。如果此时希望查看全局变量的值或者位于其他文件或其他函数的变量值时,可以用“::”操作符如下所示:
print <file::variable>
print <function::variable>
(gdb) print ‘f2.c’::x
(gdb) print ‘f2.c’::sum::x
4.2 对程序中函数的调用
print 对程序的函数进行调用,调用指定形参的值,并且返回返回值
print func(arg1,arg2,…)
(gdb) break 19
(gdb) print func(5)
4.3 查看表达式的值
print 和很多gdb的命令一样,接受一个表达式,gdb会根据当前程序运行的数据来计算这个表达式的值。
print <expression>
(gdb) print a-b
4.4 查看数组的值
下面的命令的功能为查看指定数组所有元素的值。
print <array-name>
(gdb) print a
@的左边是数组的首地址,右边是数据的长度,保存在变量len中
4.5 变量的输出格式
gdb会根据变量的类型输出变量的值,也可以自定义gdb的输出格式。
x:按16进制格式显示变量 d:按十进制格式显示变量
u:按16进制显示无符号整型 o:按八进制格式显示变量
t:按二进制格式显示变量 a:按16进制格式显示变量
c:按字符格式显示变量 f:按浮点数格式显示变量
(gdb) p/a i
4.6 查看内存
当需要查看内存中的值已发现程序运行的问题时,需要使用gdb提供的内存查看指令。
x /nfu <address>
nfu是可选的参数;n是正整数,表示显示内存的长度;f表示显示的格式;u表示从当前地址向后请求的字节数。如果不指定,,gdb默认是4个B,b表示单字节,h表示双字节,w表示四字节,g表示八字节。
(gdb) x/3uh 0x54320
h表示以双字节为一个单位,3表示三个单位,u表示按16进制显示。
4.7 自动显示变量
用户在调试程序的过程中可以设置一些自动显示的变量,当程序停住时。或是在用户单步跟踪时,这些变量会自动显示。
display/fmt expr fmt与命令x的参数一样,当用display设定好了一个或多个表达式后,程序一旦停止,gdb会自动显示所设置的表达式的值
删除所有自动显示的命令:
undisplay
删除指定的自动显示: delete display <dnums>
info display查看display设置的自动显示的信息。
启用和禁用自动显示命令如下:
disable display <dnums>
enable display <dnums>
启动和禁用所有条目
disable display enable display
4.8 设置显示选项
gdb关于设置选项内容比较多,个人感觉不是特别重要。
4.9 显示变量的历史记录
当使用gdb的print查看程序运行时的数据时,每一个print都会被gdb记录下来,gdb会以$1,$2,$3…,这样的方式为每一个print命令结构编号
(gdb) break 19
(gdb) print size-i
$1=11
(gdb) print $1 可以再次查看变量的值。
4.10 查看寄存器
info register 显示寄存器(除了浮点型)信息
info all-register 显示所有寄存器(包括浮点型)内容
info register cs 显示指定寄存器(包括浮点型)
4.11 查看使用gdb环境变量
可以在gdb的调试环境中定义自己的变量,用来保存一些调试程序中的运行数据。gdb的环境变量和UNIX一样,也是以$起头。
set <expression>
(gdb) set $foo=*object_ptr
(gdb) set $foo=50
使用环境变量时,gdb会在第一次使用时创建这个变量,而在以后的使用中,则直接对其复制。环境变量没有类型,可以为环境变量定义任意的类型,包括结构体和数组
可以使用show命令查看当前所设置的所有环境变量,命令格式如下:
show convenience
gdb的环境变量功能非常强大,可以与程序变量交互使用,参与到代码的运行中。
(gdb) set $i=0
(gdb) print bar[$i++]->contents
这之后就不需要每次都输入,只需要每次回车一次就可以了
5, 改变程序的执行
一般被调试程序会按照代码的运行顺序依次执行,gdb提供了乱序执行这种强大的功能,所以gdb可以修改程序的执行顺序,可以让程序随意地跳跃。
5.1 修改变量的值
修改调试运行时的变量值,在gdb中很容易实现,使用gdb的print或者set命令即可完成。
print <expr>
set <expr>
(gdb) print x=4
(gdb) set x=4
有时候set 变量名的时候可能与gdb本身的命令冲突,因此可以使用set var
(gdb) set var width=4
使用set width因为是gdb命令,而会出现语法错误。
5.2 跳转执行
程序的跳转执行功能可以由gdb的jump命令来完成
jump <location>
jump需要指定下一跳语句的运行点,可以是文件的行号,可以是file:line格式,可以是+num这种偏移格式。
5.3 信号的产生及处理
使用signal命令,可以产生一个信号给被调试的程序。例如,中断信号Ctrl+C。这非常方便与程序的调试,可以在程序运行的任意位置设置断点,并在断点用gdb产生一个信号,这种精确地在某处产生信号非常有利于程序的调试。
signal <signum>
Unix的系统信号同城从1到15,所以signum的取值也在这个范围。
handle命令可以控制信号的处理,命令格式如下:
handle <sig-name> <whatodo>
有两个参数一个是信号名,另外一个是接收到信号时该做什么。
可以有以下几种可能的参数:
nostop 接收到信号时,不要将它发送给程序,也不要停止程序
stop 接到信号时停止程序的执行,从而允许程序调试;显示一条表示已接收到信号的消息。
print接收到信号时显示一条消息。
noprint 接收到信号时不要显示消息,隐含着不停止程序运行
pass 将信号发送给程序,从而允许程序去处理它、停止运行或采取别的动作
nopass 停止程序运行,但不要将信号发送给程序。
(gdb) handle SIGPIPE stop print
5.4 强制调用函数
强制函数调用命令call,功能及用法与print相同,命令格式如下:
call func(arg1,arg2,…)
print 和call的区别是,如果函数返回void,call不显示,print则显示函数返回值,并把该值存入历史数据中。
5.5 强制函数返回
如果程序有调试断点在某个函数中,并且还有语句没有执行完,可以使用return命令强制函数忽略还没有执行的语句并返回,return命令后面的值会被认作函数的返回值。
return <value>
6, gdb高级应用
6.1 产生core文件
有时在gdb运行正常的程序时,在命令行下运行会出问题,运行后智慧留下一个名为core的文件。gdb可以载入core文件并检查上次运行死掉前的程序状态。有些版本的默认设置不生成core文件,可以执行如下命令允许生成core文件:ulimit –c unlimited
使用gdb载入core文件:
gdb test5 core 显示程序怎样种植并提供一条消息。
6.2 跟踪栈上数据
每个函数和它的变量都指定了一个frame,而最近调用的函数则在0号frame中。这些frame形成了一个程序运行占,要打印此栈,可以使用命令backtrace,
(gdb) bt
(gdb) frame 1 假设1好frame出错,则转到1好frame
(gdb) info locals 查看frame1下的局部变量。
6.3 绑定运行进程
为了调试core文件或程序,gdb可以绑定到一个正在运行的进程上(这个进程的程序必须编译进了调试信息)并进入到进程内。这是通过指定想要绑定gdb的程序进程ID而不是核心文件名实现的。
gcc –g test8.c –o test8
./test8 & 会显示后台运行起来的ID信息,假设是5952
gdb test8 5952 gdb会寻找一个名为5952的核心文件,当没有找到它时会绑定并进入到5952进程中
detach命令厉害进程
attach 命令绑定进程。
6.4 源文件搜索
下列命令可以在当前文件中向下搜索正则表达式:
search regexp
reverse-search regexp 向上搜索正则表达式。
上面搜索到的匹配的行号会存入环境变量$_中,可以用print命令查看
print $_
6.5 机器语言工具
有一组专用的gdb变量可以用来检查和修改计算机的通用寄存器,gdb提供了目前每一台计算机中实际使用的4个寄存器的标准名字。
6.6 其他有用的调试命令
pwd 显示当前工作目录
cd 改变当前工作目录
quit 推出gdb
shell [commandline] gdb允许在不推出调试环境的情况下运行shell命令