• gdb


    1.进入gdb:

    #gdb test -q(uiet)

    其中test为目标可执行文件,-q代表不打印那一大串版本版权信息之类的刷屏字幕。

    这里有个小常识就是用gcc编译目标文件test时,记得-g,表示可调试。

    另外,直接进入gdb而未加载可执行文件,或者加载了目标文件,想换一个其他的——可以使用

    (gdb)file test2

    或者

    (gdb)exec(-file) test2

    1.2加载core文件

    #gdb execfile core.xxxx

    加载execfile出错产生的core文件,

    Core was generated by `./coreTest'.
    Program terminated with signal 11, Segmentation fault.
    #0  0x080486e5 in main () at coreTest.cpp:16
    16        cout << s1->i << endl;    
    Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.25.el6.i686 libgcc-4.4.5-6.el6.i686 libstdc++-4.4.5-6.el6.i686

    可以看到,s1是NULL指针,从NULL指针找成员变量,core dumped。

    core.xxxx是core文件的文件名,没修改设置的话,应该在当前路径。不过大前提是打开了core文件记录:

    # ulimit -c 

    查看core文件大小,0则代表关闭

    # ulimit -c 1000

    设置core文件大小,有大小代表打开,则出错能产生文件。

    2.断点的设立:

    (gdb)b(reakpoints) <rowNums...>

    <rowNums...>代表想要设立断点的行数

    忘了哪行是什么?没关系,你可以用list

    (gdb) list
    1    #include<stdio.h>
    2    int main()
    3    {
    4        int i = 10;
    5        i = 11;
    6        printf("the address of i is %p and the value of i is %d
    ",&i,i);
    7    }
    8    

    另外,list也可以设置显示行数和指定位置的

    (gdb)list 

    (gdb)list 10

    (gdb)list 5,10

    (gdb)func

    比如默认显示10行,可以指定第5到第10行,指定显示某函数代码,等等。

    不过最好的建议还是开俩终端,一边看代码,一边调试,看着舒服。

    另外

    (gdb) layout

    也可以显示程序代码,还是用框子圈起来的。

    (gdb)b func

    (gdb)b *func

    在函数func()设立断点,星号代表进入前,查结果——一目了然~!

    (gdb) b *main
    Breakpoint 1 at 0x80483e4: file testPC.c, line 3.
    (gdb) b main
    Breakpoint 2 at 0x80483ed: file testPC.c, line 4.
    (gdb) info b
    Num     Type           Disp Enb Address    What
    1       breakpoint     keep y   0x080483e4 in main at testPC.c:3
    2       breakpoint     keep y   0x080483ed in main at testPC.c:4

    其中

    (gdb)info b(reakpoints)

    相当于列表打印所有已设立的断点。有了断点,当然也可以删掉断点,看到列表中左边的”Num“了么,用得上:

    (gdb) d 1
    (gdb) info b
    Num     Type           Disp Enb Address    What
    2       breakpoint     keep y   0x080483ed in main at testPC.c:4
    (gdb) 

    (gdb)d(elete) Num

    代表删除第Num个断点。可以看到第一个断点被删了。

    3.基本调试流程

    有了断点,就该用上了。

    第一步,开始运行程序:

    (gdb)r(un) 

    (gdb)n(ext)

    (gdb)s(tep)

    和其他调试相仿,这两条分别代表step over和step in,

    (gdb)c(ontinue)

    run和continue功能其实差不多,都是继续往下运行,直到下一个断点停下来,不过场合不一样罢了:run是开始运行前的启动命令,continue是运行中的命令。

    4.汇编style:

    基本的流程走完了,该引入汇编了。

    i代表指令(instruction)

    不很确定,至少你不能用instruction代替i,至少,先理解为汇编的意思。

    前边的指令加上i就显示了汇编代码,例如:

    n(ext)i

    s(tep)i

    要想一步一步看汇编代码和执行过程,

    (gdb)ni

    (gdb)si

    是必不可少的,不过你可以用回车表示继续使用上一次的命令。

    5.print:

    gdb提供了打印功能:

    示例:

    (gdb)p(rint) i

    打印i变量当前的值。

    不仅程序中的变量,寄存器的值也能打印

    (gdb) p $pc

    两个小疑问:

    5.1.$pc代表什么,除了它还能打印什么?

    这句话其实就是打印程序计数器的值。

    先说寄存器,除了$pc,还有%esp,%edp等等等等,

    具体到底能打印那些,又要牵扯到另一条命令了,下面看一例:

    (gdb)i(nfo) r(eg)
    (gdb)
    eax            0x80484f0    134513904
    ecx            0xbffff304    -1073745148
    edx            0xb    11
    ebx            0xb7fc2ff4    -1208209420
    esp            0xbffff240    0xbffff240
    ebp            0xbffff268    0xbffff268
    esi            0x0    0
    edi            0x0    0
    eip            0x8048406    0x8048406 <main+34>
    eflags         0x200282    [ SF IF ID ]
    cs             0x73    115
    ss             0x7b    123
    ds             0x7b    123
    es             0x7b    123
    fs             0x0    0
    gs             0x33    51

    上边看到的都可以print,而且能发现个小规律,这个info reg打印的,除了最左边是寄存器名称外,中间是寄存器存的值(也就是一个内存地址),右边是这个值对应的内存地址中的值。打印一下$eax可验证:

    (gdb) p $eax
    $3 = 134513904

    其实用法远不止于此,比如p $打印上一次打印的值,$$打印上上次打印过的值。print其实是有计数器的,每次print打印,其实都有一个类似count++在内部发生,使用print $num 能显示第num个打印结果(如上,p $3就等价于p $eax

    5.2.C语言中printf有打印格式控制,那么gdb的print呢?

    也有~

    (gdb)p i
    (gdb)p/a i
    (gdb)p/c i
    (gdb)p/f i
    (gdb)p/x i
    (gdb)p/o i
    (gdb)p/d i
    (gdb)p/t i
    ......

    反斜杠后边这几个参数分别控制打印的进制与格式:
    f浮点,c字符。。。
    t为二进制,o八,x十六,d十
    另外:a和x同样是打印十六进制,区别呢?可能就是不同名但同功能

    理念有点像C语言编程时候加printf打印变量来监视程序。在gdb中你也可以随时打印各变量的值,而且更为强大

    6.bt

    有时普通打印法已经很难跟住bug了,另一个原因是段错误就系统重启(其实是工程设置的信号处理,SIGSEGV段错误信号重启系统。),而gdb能在重启之前截断程序运行,从而卡在出错点,防止重启系统。

    不过光卡在那也不行啊,一层套一层,那么多的函数调用,你不进去看不到东西啊,而且再输入n(next)往下走是看不到已经运行完的错误的,所以就谈到bt(backtrace)命令——回溯。

    7.运行中的进程

    都知道,运行gdb加载文件,或在gdb内部用file加载文件,想再运行程序等于新开一个进程。

    现在想调试一个运行中的进程,而不是新启动一个进程。

    #ps -aux | grep execFile

    找到运行中的进程PID,

    使用

    #gdb execFile PID

    #gdb 

    (gdb) attach PID

    即可连接正在运行中的进程,进行调试。 

    8.etc.

    其他的乱七八糟,例如examine。

    (e)xamine:功能和display差不太多,区别就是display是一种设置,每次跳命令显示一次,x是主动显示。

    x/3i $pc显示3条指令(3为示范,数字可选)
    (gdb)(e)x(amine)
    语法:
    x/<n/f/u> <addr>
    n选择从当前地址向后显示几个
    f是显示格式,还有s字符串和i整型
    u表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4个bytes。u参数可以用下面的字符来代替,b表示单字节,h表示双字节,w表示四字节,g表示八字节。当我们指定了字节长度后,GDB会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来。

    例子:
    x/3uh 0x54320表示,从地址0x54320读取,h表示以双字节为单位,3表示三个单位,u表示十六进制

    ===========================================================================================================

    set 设置变量,可以在运行时通过断点加手动设置的方法来动态的改变变量值。也可以在程序运行前设置程序运行参数》》set args hello world

    shell,顾名思义,使用shell命令,省得切出去了,另外,貌似也可以达到set args的效果。因为这下你终于可以直接在gdb界面通过命令行运行程序了

    (gdb) shell ls

    (gdb) shell ./a.out param1 param2

    两例见

    http://blog.csdn.net/huqinweI987/article/details/50706743

     

    ===========================================================================================================

    HELP:

    前边print提到功能太多,方法太多,想知道最详细的,请

    (gdb) help print

    关于help的强大和使用方法,不赘述了,使用

    (gdb) help

    就什么都知道了。


    ----------------------------------------------------------------------------------------------------------------

    ADDITIONAL:

    GDB7.0以上(7.4)

    可用如下套路:

    (gdb)set disassemble-next-on

    (gdb)b main
    (gdb)r
    (gdb)ni
    (gdb)ni
    .....
    这个也是比较不错比较直观的方式

    disas /m main
    让C和汇编同时显示

  • 相关阅读:
    hibernate.cfg.xml
    java util 巧用
    Ant
    WEB文件上传二 (Struts 文件上传)
    web文件上传一学习记录 (简单的web浏览器可读文件的上传,servlet 文件上传)
    long类型的时间转为n秒前n分钟前n小时前或者日期
    各种String类型的时间转long型,long转String
    Android 内容提供者(ContentProvider)的简单实用
    sql性能优化总结(转)
    数据添加到DataTable
  • 原文地址:https://www.cnblogs.com/itsad/p/8022984.html
Copyright © 2020-2023  润新知