GDB 基本用法

  • GDB 简介
  •         GDB:the GNU Project Debugger。
            简单来说,GDB 就是 Linux(或者说 *nix ?)环境下最通用的调试工具,它是非图形化的,人机通过“键入”各种指令直接交互,省去了鼠标点来点去之繁琐,并且在一定程度上据说也可以实现自动化调试。
            按官方的说法,GDB 可以让你在另一个程序运行的时候看到程序内部发生的变化,或者看到程序崩溃时的当前操作。更具体地,GDB 主要可以做 4 件事:

    • 启动程序,并指定任意运行条件
    • 在给定条件下停止程序执行
    • 在程序停止时,检查已经发生了什么
    • 改变程序,“越过”一个 bug 去寻找更多 bug

            不过知道这些其实没什么用处,GDB 归根结底是拿来用的,将之应用于实际才是硬道理。作为一个已经学习计算机科学半个多时代的“人才”,鄙人接触 Linux 也已经有几个年头,对 GDB 的大名岂知是“早有耳闻”,简直是“如雷贯耳”并且“久仰久仰”。可惜此前从未用过,每次别人说“你用 GDB 跟踪一下”的时候,鄙人总是搪塞过去,转而默默地用“printf”。所幸,最近终于大脑开窍,主动了解、学习起了 GDB,不得不说其简洁易上手,好用得紧。而这篇,就算是我对 GDB 基本用法的一个总结。

  • 编译选项
  •         加了调试选项才能正确地显示函数、变量和代码等信息,选项很简单,就一个 -g

  • 启动与退出
  •         在最一般的情况下,比如调试 a.out,只需要“gdb a.out”即可。其他用法还包括指定 core dump 后的 dump 文件和调试服务程序时绑定 Pid。
            退出的命令是 quit,快捷键 Ctrl+d 。
            在交互中,直接回车代表输入和上一条一样的命令,这在单步调试时比较有用。另外支持用 TAB 键自动补全。

  • 查看代码
  •         查看代码用 list,简写为 l。

    (gdb) l
    (gdb) l <linenum>      #默认输出行号附近 10 行代码
    
  • 断点设置与维护
  •         设置断点用 break,简写为 b。基本用法有:

    (gdb) b <linenum>         # 在某行设置断点
    (gdb) b <funcname>      # 在某一函数处设置断点
    (gdb) info b                     # 查看当前断点
    

            设置断点后,还可以维护这些断点,比如删除、disable 以及激活等。其实维护的可能不仅仅是代码中的断点,还可能有观察点等,统称为停止点。

    (gdb) delete                            # 删除所有断点
    (gdb) delete <pointnum>      # 删除某一断点
    (gdb) disable                          # disable 所有断点,简写 dis
    (gdb) dis <pointnum>           # disable 某一断点
    (gdb) enable                           # enable 所有断点,简写 en
    (gdb) en <pointnum>            # enable 某一断点
    
  • 运行和单步调试
  • (gdb) r                  # 即 run,从开始运行
    (gdb) c                 # continue,继续运行到某一停止点
    (gdb) n                 # next,单步调试,不会进入函数
    (gdb) s                 # step,单步调试,会进入函数内部
    
  • 查看变量、数组、栈
  • (gdb) p i                        # print,打印变量或静态数组 i
    (gdb) p *array@len     # 打印动态数组 array,指定长度 len
    (gdb) bt                        # backtrace,查看栈信息,即函数调用信息
    
  • 退出函数、循环体
  • (gdb) u            # until,执行到当前循环退出
    (gdb) finish     # 执行到当前函数退出
    
  • 自动显示
  •         可以用 display 命令设置自动显示的变量,当程序停止或单步跟踪时变量会自动打印。具体用法有:

    (gdb) display <expr>
    (gdb) display/<fmt> <expr> 
    (gdb) display/<fmt> <addr>            # addr 代表内存地址
    (gdb) undisplay <dnums...>            # 删除自动显示
    (gdb) delete display <dnums...>     # 删除自动显示
    (gdb) disable display <dnums...>   # 使某个自动显示失效
    (gdb) enable display <dnums...>    # 激活被失效的自动显示
    (gdb) info display                             # 查看 display 信息
    
  • 输出格式控制
  •         就像 printf 中的格式控制一样,gdb 可以按照不同格式打印值,具体有:

    x    按十六进制格式显示变量。
    d    按十进制格式显示变量。
    u    按十六进制格式显示无符号整型。
    o    按八进制格式显示变量。
    t    按二进制格式显示变量。 
    a    按十六进制格式显示变量。
    c    按字符格式显示变量。
    f    按浮点数格式显示变量。
    

    比如:

    (gdb) p i
    $2 = 101
    (gdb) p/a i
    $3 = 0x65
    (gdb) p/x i
    $4 = 0x65
    (gdb) p/t i
    $5 = 1100101
    (gdb) p/c i
    $6 = 101 'e'
    (gdb) p/f i
    $7 = 1.41531145e-43
    
  • 查看内存
  •         使用 examine 命令查看内存,简写为 x,其提供 3 个可选选项:n、f、u。

    x/<n/f/u>  <addr>
    n    显示几个单位的地址内容
    f    显示的格式
    u    从当前地址请求的字节数,默认 4B。
           b - 单字节,h - 双字节,
           w - 4字节, g - 8字节
    

    例如,x /3uh 0x8170 表示,从地址 0x8170 处读取内存,以双字节为单位,读取 3 个单位并以 16 进制显示。

  • 参考资料
  • 发表评论

    电子邮件地址不会被公开。 必填项已用*标注