Chinaunix首页 | 论坛 | 博客
  • 博客访问: 565779
  • 博文数量: 94
  • 博客积分: 1631
  • 博客等级: 上尉
  • 技术积分: 586
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-28 12:16
文章分类

全部博文(94)

文章存档

2014年(1)

2013年(11)

2012年(69)

2011年(7)

2010年(6)

我的朋友

分类: C/C++

2013-11-25 13:59:15

这里只是一个摘要。具体的细节还需要去看manual。 

1 info 用来描述你的程序的状态,比如info b就是显示出当前的程序的所有断点. 
2 set 用来设置一些环境变量的值,比如set prompt $. 
3 show用来描述gdb自己的状态. 
编译要用-g选项. 
然后用gdb +程序名,或者直接gdb后,用file + 文件名加载程序. 

1 run/r 运行程序. 
2 set args 设置程序的参数. 
3 path directory 加一个目录到环境变量path 
4 set directory 设置gdb的工作目录 
5 pwd 当前的工作目录 
6 attch process-id 调试 运行的进程 
  dettach  当调试进程完毕,release 掉gdb的控制. 

调试多线程. 

1 thread threadno 选择当前的线程. 
2 info thread 查看当前程序的线程. 

debug多进程: 

默认情况下,当fork一个子进程之后,gdb会继续debug父进程,而子进程会运行下去.不过我们能够改变这个. 
set follow-fork-mode mode 这里mode可以为parent或者child. parent是默认值,而child的话就是gdb继续debug子进程,而父进程会运行下去. 
如果你想要同时debug父子进程,也可以设置: 
set detach-on-fork mode 默认是on,也就是只能debug一个进程,如果改为off则可以同时debug父子进程. 
保存一个书签稍后返回. 

checkpoint 保存当前的程序的状态. 
restart checkpoint-id 返回到checkpoint-id那个点.这个值可以用info checkpoint来查看 
breakpoint,watchpoint以及catchpoint 
breakpoint 就是断点. 
watchpoint 就是用来检测变量的改变,他可以看做是特殊的断点,也就是当变量改变时停止程序. 
catchpoint 是另外一种特殊的断点,用来监测某一事件的发生,有点类似其它语言中的异常. 

1 设置Breakpoint 
break location 设置断点.location可以为行号,函数名或者指令地址. 
break 设置断点,不过这个断点为当前栈帧的下一条指令. 
break location if condition 当condition为真时,程序到达这个断点才起作用. 
tbreaks args, 一次性的断点. 
rbreaks regex 设置断点在所有与regex匹配的函数.这个正则表达式的语义与grep的相同. 

2 设置watchpoint 
watch expr[thread threadno] 设置检测变量expr,后面可以跟着改变这个变量的线程.如果跟着线程号,则说明只有当这个线程改变变量时,程序才会stop. 
rwatch expr[thread threadno] 上面是监测变量改变,而这个命令是监测程序读取变量. 
awatch expr[thread threadno] 当expr要么被读,要么被写时,程序直接break. 

3 设置catchpoint 
catch event 当event发生的时候程序停止. 
event可以是下面的几种类型: throw ,catch,exception,exception unhandled,assert,exec,fork,vfork. 
tcatch event 一次性的监测事件. 

删除断点 
clear 删除在当前的栈帧的将要被执行的下一条指令断点. 
clear location 删除location位置的断点.其实更有用的是下面几个命令: 
clear function,clear filename:function ,clear linenum,clear filename:linenum. 
delete [breakpoints][range...]  其实也就是删除多个断点,如果没有range,咋就是删除全部断点. 

关闭断点 
一个断点(包括 watchpoint和catchpoint)可以有下面四种状态. 

打开,关闭,enabled once,enabled for deletion 
disable [breakpoints][range..]  关闭指定的断点或者全部断点(如果没有range) 
enable [breakpoints][range..] 打开指定的断点或者全部断点(如果没有range) 
enable [breakpoints] once range  临时打开指定的断点(也就是说是一次性的,. 
enable [breakpoints] delete range 临时打开指定的断点并只工作一次,也就是一次之后这个断点将会被删除. 
break condition 
contidition bnum expression  当expression为真的时候,程序到达这个断点才会停止. 
contidition bnum 从断点bnum删除掉一个condition. 
ignore bnum count 设置一个断点bnum的忽略次数为count.也就是只有count次数后,这个断点才会起作用. 

断点命令列表 
这个主要是用来当到达这个断点,程序停止后,你想要执行一连串的命令.格式为: 
Java代码  收藏代码
  1. command [bnum]  
  2. ... command-list ..  
  3. end  
指定一堆命令给断点bnum.如果想删除命令的话就把command-list置为空就行了. 
如果没有bnum,则这个command指的是最后设置的一个断点. 
这里有个例子: 
Java代码  收藏代码
  1. break 403  
  2. commands  
  3. ///不输出任何东西  
  4. silent  
  5. ///改变x的值  
  6. set x = y + 4  
  7. ///然后continue  
  8. cont  
  9. end  
接下来来看continue和step 
continue表示让程序继续执行,直到下一个断点或者执行完毕。 
step表示让程序执行一行代码或者说一条机器指令(依赖于你选择的命令)。 
下面来看命令: 
Java代码  收藏代码
  1. continue [ignore-count]  
  2. c [ignore-count]  
  3. fg [ignore-count]  
这几个命令都是resume一个程序,然后参数ignore-count表示忽略当前这个断点的次数。 
step [count] 
继续运行程序直到抵达一个新的代码行(它会跟入函数).这里要记住step只会停止在source line的第一条指令。 
如果加上count参数则表示它会step count次。如果遇到断点则会停止。 
next [count] 
和step很类似,区别就是不会跟进函数。 
Java代码  收藏代码
  1. set step-mode  
  2. set step-mode on  
  3. set step-mode off  
on就可以使step停止在没有debug信息的函数的第一条指令上。off则是直接执行完这个函数。 
这里要注意上面的命令都只是跳一行代码。而不是一条指令。 
util  继续运行直到source line通过了当前的行。这个命令主要是针对循环语句中的step。比如你在循环结尾设置util,则只有当循环退出时才会在这个断点停止。而不是每次都停止。 
util location 继续运行直到指定的location,或者当前的栈帧返回。 
advance location 继续运行直到给定的location,这个相比与上面的命令,它就象全局的。 
stepi [arg] 
执行一条机器指令。 arg表示次数。 
nexti [arg] 
和next类似只不过执行的是一条机器指令。 
下来来看信号。 
gdb可以监测在你的程序中的任何信号。 
来看命令。 
handle signal [keywords...] 
这个命令用来改变信号signal(名字或者数字)在gdb中的行为。 
其中关键就是keywords.在这里keywords可以为下面几种类型: 
1 nostop gdb接收到信号不会停止程序,而只是打印出一段message 
2 stop 和上面类似只不过会停止程序。 
3 print 当信号发生必须打印一条消息通知。 
4 noprint 信号发生,gdb将不会打印任何东西。 
5 pass和noignore 这两个是同义的。表示信号对你的程序是可见的。 
6 nopass和ignore 这两个也是同义的。和上面相反。。 
在gdb中,当你的程序由于一个信号而停止后,直到你继续执行,否则信号对你的程序是不可见得。也就是说当gdb捕捉到信号,我们可以用nopass或者ignore来使信号对我们的程序为不可见。 

最后来看下多线程程序的调试。 
首先来看多线程调试的几种模式。 
1 all-stop模式。 
在这种模式中,当你的程序在gdb由于任何原因而停止,此时所有的线程都会停止。而不仅仅是当前的线程。一般来说gdb不能单步所有的线程。因为线程调度gdb是无法控制的。无论什么时候当gdb停止你的程序,它都会自动切换到触发断点的那个线程。 
在一些os中我们可以通过lock线程调度器,从而达到只有一个线程在运行。 
set scheduler-locking mode 
设置模式,如果mode是off,则表示没有lock,则任何线程在任何时候都有可能在运行。当mode为on的时候,锁定其他的线程,也就是只有当前线程在执行。也就是你单步的时候其他线程是不会运行的。这个对我们只关注本线程比较重要。 
默认情况下,当你键入step或者next命令时,gdb只允许当前进程的线程运行。我们可以通过命令来修改这个默认值。 
set schedule-multiple mode 
当mode为on则所有进程的所有线程都匀许运行。否则只有当前的进程的线程能够resume。 

2 none-stop模式。 

顾名思义,当程序在gdb中停止,只有当前的线程会被停止,而其他的线程将会继续运行。 
这个时候step,next这些命令就只对当前的线程起作用。 
我们要打开这个模式需要这样操作: 
Java代码  收藏代码
  1. # Enable the async interface.  
  2. set target-async 1  
  3. # If using the CLI, pagination breaks non-stop.  
  4. set pagination off  
  5. # Finally, turn it on!  
  6. set non-stop on  
这里要注意打开这个模式必须得在你attach或运行这个程序或者进程之前才能进行。 
Background Execution 
gdb执行命令有两种类型:前台的(同步)和后台(异步)的。 
区别很简单,前台的话,gdb在输出提示符之前会等待程序report一些线程已经终止的信息。而异步的则是直接返回。 
我们需要显式打开异步模式。 
set target-async on 
下面就是支持异步的命令: 
Java代码  收藏代码
  1. run   
  2. attach   
  3. step   
  4. stepi   
  5. next   
  6. nexti   
  7. continue   
  8. finish   
  9. until  
通过上面我们可以看到异步模式主要用在none-stop模式中。 
如果你想停止后台运行的程序,那么使用interrupt 
在all-stop模式中interrupt将会停止所有的线程。而在none-stop中只会停止当前线程。interrupt -a此时就能停止所有线程。’ 
当你有多个线程,你此时只想给某个线程设置断点,这个时候可以用这个命令: 
break linespec thread threadno 
break linespec thread threadno if ... 
linespec为源码行号,threadno为线程id。 
最后来看下多线程调试中可能会遇到的一个问题: 
如果一个线程在一个断点,或者由于其他什么原因停止,此时另外的线程阻塞在一个系统调用。这个时候这个系统调用就有可能会过早的返回。因此我们在调用系统调用,最好都要检测它的返回值。 
举个例子: 
sleep (10); 
这个我们应该改成这样: 
Java代码  收藏代码
  1. int unslept = 10;  
  2. while (unslept > 0)  
  3. unslept = sleep (unslept); 
阅读(1043) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~