注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

天马行空

宠辱不惊,闲看庭前花开花落;去留无意,漫观天外云展云舒……

 
 
 

日志

 
 
 
 

GDB调试教程  

2012-09-06 18:11:00|  分类: LINUX |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

gdb调试基本知识

调试器指示的是将要执行的代码行
只有在编译时拥有调试符号(gcc -g)的程序才能在调试时看到源代码
同一行上有多个断点时,GDB仅中断在断点号最小的那个断点上
断点可以设置在同一程序的不同文件中
在任何给定时间,GDB只有一个焦点,即当前“活动”的文件
源文件改变后,断点发生移动,但是断点属性的行号不变

断点(breakpoints)的分类

断点(break):程序中的特定位置,可以设置在不同的文件中
临时断点(tbreak):中断一次后自动删除
条件断点(break if):满足特定条件后才会中断
监视点(watch):特定的内存位置
捕获点(catch):特定事件

断点属性(info breakpoints)

Num     Type           Disp Enb Address    What 1       breakpoint     keep y   0x080485b9 in main at ../src/01_INS.c:71 2       watchpoint     keep y              num_y ... 

Num: 断点号
Type: 断点类型(断点、监视点、捕获点)
Disp: 断点部署(该断点下次中断后如何处理该断点?)
keep:保持不变
del: 删除该断点
dis: 禁用该断点
Enb: 断点当前启用状态
What: 断点位置

断点的操作:

设置断点:

break [filename:]function
break [filename:]line_number

删除断点:

delete breakpoint_list
clear [filename:]function
clear [filename:]line_number

禁用/启用:

disable/enable 无参数情况下将会禁用/启用所有断点
disable breakpoint_list
enable breakpoint_list
enable once breakpoint_list 该断点下次中断后自动禁用

移动断点:

GDB中移动断点的唯一方法是删除断点后在新的位置再放置一个一模一样的断点
但是DDD中只需要托拽断点符号就能移动到新位置,并且保留该断点的所有属性

恢复执行

step和next

step和next在Eclipse中分别对应step intostep over命令
根据自顶向下调试程序的原则,应该尽量使用next进行调试,当发现该函数执行后结果与预期不符,才转用step进入函数内部进行调试。

continue

该命令恢复被GDB中断的程序继续运行,直到遇到断点或者程序结束。
用法: continue [n]
参数n使GDB忽略接下来的N个断点。
continue对应Eclipse中的Resume

finish

finish命令恢复程序的运行,并返回到上层函数后停止
finish对应Eclipse中的step return

until

无参的until命令恢复程序的运行,并执行完循环的其余部分
until官方定义:执行程序,知道到达当前循环体外的下一行源代码
实际上,由于高级语言到机器语言在顺序上并不一定完全对应,until在到达内存地址比当前高的机器指令后就会停止
用法:
until [filename:]line_number
until [filename:]function
以上两种用法在到达指定的行号或者函数后即停止

条件断点

break if

用法:
break [break-args] if (condition)
例如:

break main if argc > 1 break 180 if (string == NULL && i < 0) break test.c:34 if (x & y) == 1 break myfunc if i % (j + 3) != 0 break 44 if strlen(mystring) == 0 

condition

与break if类似,只是condition只能用在已存在的断点上。
用法:
condition <break_list(condition)
例如:
cond 3 i == 3
将会在断点3上附加条件(i == 3)

条件表达式的返回值

上面的条件表达式计算后结果的类型是什么?答案是int型。
这是因为唯一能在断点条件表达式中使用的返回值类型为int
这意味着,如果调用了像cos()这样的数学函数,会导致预料之外的值。
如(在已经连接到libm库的前提下):

(gdb) print cos(0.0) $1 = -1073776640 

解决这个问题的方法是类型转换,我们来看这个例子

(gdb) set $p = (double (*) (double)) cos (gdb) print cos(0.0) $2 = -1073776640 (gdb) print $p(0.0) $3 = 1 

在这里,通过设置变量$p为“一个参数为double,返回类型为double的指向cos函数入口地址的函数指针”,来对参数进行强制类型转换

为断点设置命令列表

我们知道,设置一个断点并且在上面中断后,我们必然会查询一些变量或者做一些其他动作。
如果这些动作可以一气呵成,岂不妙哉!使用命令列表(commands)就能实现这个功能。

步骤如下:

  1. 建立断点
  2. 使用commands命令
  3. 用法:
    commands break_list
    例如:

    (gdb) commands 1 Type commands for when breakpoint 1 is hit, one per line. End with a line saying just "end". >silent  >printf "n = %d \n", n >continue >end 

定义宏(define)

宏可以在调试期间录制,也可以事先录制在.gdbinit文件中。
GDB的宏就像shell脚本一样,可以传入参数,依次是$arg0, $arg1, ...
定义好宏之后,可以用在命令列表中。
注意,宏并不支持所有的GDB命令,如silent就不能用在宏中。
以上节为例,我们录制一个宏:

define print_and_go print $arg0 continue end 

然后在断点1处定义如下命令:

commands 1 silent print_and_go end 

监视点(watch)

用法:
watch var

注意

监视点的设定不依赖于断点的位置,但是与变量的作用域有关,也就是说,要设置监视点必须在程序运行时才可设置。

在不确定发生问题的地方时,通过使用监视点的条件表达式,可以非常方便地找出问题代码:

watch i > 999 

一旦i > 999,程序就会被中断,GDB指出改变条件的代码。

  评论这张
 
阅读(827)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018