gdb一般用法(更新中)

对于源码分析的环境是:window下可以利用Source insight进行代码框架性的了解:如可以快速查看函数的定义或者应用等,它的可视化提供了很强大的功能。在linux下使用Source Navigator也可以达到可实现效果。如果是比较细的调试还是使用gcc 它可以利用tui方式或者DDD方式来补助。


错误类型:1.死循环    ------Ctrl+C  然后list可以找到死循环的位置

          2.异常中断   -----可以通过转储核心来进行调试
          3.第三种就是和预想不合结果:  断点的方法和下面讲的主要方法:

段错误 :一般是越界,访问非法内存空间

         信号处理---- 》转储核心 


gdb namefile.o -tui方式;ctrl+X+A进行gbd tui切换; Ctrl+p Ctrl+N 来实现gdb代码记忆回滚


. TUI模式下有4个窗口,
(cmd)command 命令窗口. 可以键入调试命令
(src)source 源代码窗口. 显示当前行,断点等信息
(asm)assembly 汇编代码窗口
(reg)register 寄存器窗口


layout
用以修改窗口布局
 help layout
 layout src
 layout asm
 layout split


可以实现想正常term下的左右上下移动:
我们可以通过focus命令来调整焦点位置,默认情况下是在src窗口,通过focus next命令, 焦点就移到cmd窗口了,这时候就可以像以前一样,通过方向键来切换到上一条命令和下一条命令。
help focus
 focus cmd
 focus src


有条件的断点:
break 30 if num_y==1 或者 condition 1 num_y==1
临时断点:
tbreak  
如果要重用老的命令行参数 直接用run来运行。(一般调试的时候开3个终端,一个gdb(一般不关),一个用来vim ,一个用来编译)
run 命令后面加命令行参数;
显示当前的代码:
list 
info break的到断点信息  delete 断点序号(如3等)
break num行号
break path/file.c:num
break function

clear除下一个断点  
clear foo 
断点的可用性设置(不想删除自是暂时设置其属性)
enable disable
设置一次性属性 
(enable once breakpoint-list)
下一步
n  有交互性,即是可以看到输入输出
s(真正的下一行代码指令)它不会有交互性


finish恢复执行到函数返回后;
until 能跳出循环然后执行下一步;

使用gdb调试程序的时候,有时候需要设定多个断点,重复执行某些操作,而这些操作写起来比较麻烦,这个时候就应该想起来用gdb命令脚本了,它能够很好的完成这些工作。
以设置多个断点为例,我写的命令脚本为
---------------------------------------------------
#filename: .gdbinit
#gdb will read it when starting
file test_gdbscript
set args hello
b main
b foo
r
---------------------------------------------------
有两种方式来使用这个脚本:
1)启动gdb时候
gdb在启动的时候,会在当前目录下查找".gdbinit"这个文件,并把它的内容作为gdb命令进行解释,所以如果我把脚本命名为".gdbinit",这样在启动的时候就会处理这些命令。
2)gdb运行期间
可以使用 source script-file 来解释gdb命令脚本script-file

断点命令列表:(多次同一个断点要求做一样事情的时候,可以利用断点命令列表来方便查看调试)
  commands breakpoint-num
  commands
  end
 如:

 break  foo  (它的标示符是1)


 commands 1    ------------>commands breakpoint-num
 silent                     ------不用标记断点时候的代码信息 
 printf "foo was pass %d",n ------  commands
 continue                   ------- 下一个继续下一步
 end


创建宏来方便其他程序和其他代码中方便利用做同样类型的实现
  define print_info
  printf $arg0,$arg1
  continue
  end


断点命令列表作为一个宏的形式来调用
 commands 1
 silent
 print_info "foo was pass %d\n" n
 end

watch i>4 监视点的设立,当i变化到》4的时候那么就停下来,
watch j   当j变化的时候就停下来
由于watch是有作用域的所以它要先定义后才能生效,超出作用域将自动取消


显示和检查变量:

1.print  如果是在输出数值的时候只想输出一部分那么可以这样用:

p *array@len
@的左边是数组的首地址的值,也就是变量array所指向的内容,右边则是数据的长度,其保存在变量len中,其输出结果,大约是下面这个样子的:
(gdb) p *array@len
$1 = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40}


@的左边是数组的首地址的值,也就是变量array所指向的内容,右边则是数据的长度,其保存在变量len中,其输出结果,大约是下面这个样子的:

(gdb) p *array@len
$1 = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40}

2.display 如果每次遇到断点的时候都print同样的内容,那么就用display,它在每次断点的时候都执行一遍
3.还可以利用commands对于没次到断点时都执行它的command内容,这部分在断点命令列表中有讲
如:b 37
    commands 1
    p temp->val


    if(temp->left!=0)
      p tmp->left->val
    else
    printf "%s\n" "none"
    end


    if 
      ....
    else
    end
    
    end  
4.利用commands中call 要执行的函数
  commands 2
  printf "......you data......"
  call printdata(root)
  end

C++中引用gdb(gdb主要是用在C中,C++一般都在集成环境中进行调试如:QT,vC++)
  p *node::root     ----------root是node类中的Static指针类型

  ptype  node          --------可以看到node的类型;


gdb对于多线程程序:

 

follow-fork-mode   对于父进程fork子进程,它可以控制是对父进程 还是对子进程进行调试;

set follow-fork-mode child|parent

parent:继续调试父进程,子进程不受影响

child:调试子进程,父进程不受影响

它可以配合detach-on-fork来完成

Set detach-on-fork [on|off]

默认下detach-on-fork为on,所以默认条件下不是调试的进程不受影响。

如果设置为off那么不被调试的进程会被suspended阻塞起来。

 

 

如果对于有很多代的进程,即是有父-子-孙….这样就不能用上面的进行调试了,

可以利用attach进行进程调试:(detach用来分离调试)

(ps –ef|grep process_name找到该进程,然后通过pstree –H process_id来查看它们的关系)

启动用gdb,attach该进程:但是现在有一个问题那就是attach的进程不可控,它已经在运行了。

解决方法:1.可以通过设置特殊条件来实现:

1.      在编译运行程序的时候加一个条件,让子程序是在睡眠,而不是运行

2.       当gdb进去之后设置了断点,我们把使其条件满足,然后才开始运行

3.至于这段代码所采用的条件,看你的偏好了。比如我们可以检查一个指定的环境变量的值,或者检查一个特定的文件存不存在。以文件为例,其形式可以如下:

void debug_wait(char *tag_file)

{

               while(1)

            {

             if (tag_file存在)

                睡眠一段时间;

           else

              break;

            }

}

把这段代码加在子开始的地方就行了。这可以通过删除文件来进行条件的满足!

 

 

如果已经确定了自己要调试的文件代码;那么还可以用下面方法来进行:

Gdb wrapper

   这这种方法可以不用设置条件,只是要编辑一个文件就行了。

1.      很多时候父进程fork后是,子进程会调用exec族函数执行新代码。那么我们可以把exec调的文件编成一个文件shell文件里面的内容是:

  #!/bin/sh

 Xterm –e gdb  execwantto.binary(即是exec要进行执行的代码二进制文件)

 

Xterm –e 是为了有中断可以进行gdb交互控制;

如果程序在exec的时候还传人了参数可以改成这样:

xterm -e gdb --args  execwantto.binary$@

 

这个方法首先要我们找到exec要执行的二进制文件execwantto.binary。

如果是远程要利用VNC进行远程调试。

 

Info inferiors可以查看现在调试中的进程,有*的表示正在attch的进程!

Inferior <infer number>可以进行切换

Detach inferior infer_number 和 detach process_ip等价

多线程:

 咨询线程: infothreads

 切换调试进程:thread<thread number>

多线程,多进程调试例子请看:http://blog.csdn.net/pbymw8iwm/article/details/7876797


3). 设置捕捉点(CatchPoint)

    设置捕捉点来捕捉程序运行时的一些事件。如:载入共享库(动态链接库)或是C++的异常。设置捕捉点的格式如下:

    

Catch

如:catch exec

    Catch fork

    当event发生时,停住程序。event可以是下面的内容:

    1、throw 一个C++抛出的异常。(throw为关键字)

    2、catch 一个C++捕捉到的异常。(catch为关键字)

    3、exec 调用系统调用exec时。(exec为关键字,目前此功能只在HP-UX下有用)

    4、fork 调用系统调用fork时。(fork为关键字,目前此功能只在HP-UX下有用)

    5、vfork 调用系统调用vfork时。(vfork为关键字,目前此功能只在HP-UX下有用)

    6、load 或 load 载入共享库(动态链接库)时。(load为关键字,目前此功能只在HP-UX下有用)

    7、unload 或 unload 卸载共享库(动态链接库)时。(unload为关键字,目前此功能只在HP-UX下有用)



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值