GDB 常用命令

Core Dump
之前编写 UniMRCP ASR Plugin 的时候可谓是顺风顺水,敲完代码运行竟然就可以了。本以为 TTS 更简单一些,安装、运行,然后“segmentation fault (core dumped)”。看来是时候祭出调试神器 GDB 了。

Core Dump

当程序运行的过程中异常终止或崩溃,操作系统会将程序当时的内存状态记录下来,保存在一个文件中,这种行为就叫做Core Dump。

生成 Core Dump 文件

Linux 默认情况下是没有开启 Core Dump 的。

  • 在终端中输入命令ulimit -c,输出如果是 0,说明当前 Core Dump 是关闭的。
  • 使用ulimit -c unlimited来开启 Core Dump 功能,unlimited 是指不限制 Core Dump 文件大小,如果要限制,将 unlimited 替换为文件最大大小(KB)。

Core Dump 文件存储位置及文件名

Core 文件默认保存在执行目录下,可进行修改:

1
echo “/data/coredump/core.%e.%p.%t” >/proc/sys/kernel/core_pattern

保存在“/data/coredump”目录下,文件名为“core.程序名.进程号.时间”。

模版部分变量:

  • %% 单个%字符
  • %p 所dump进程的进程ID
  • %u 所dump进程的实际用户ID
  • %g 所dump进程的实际组ID
  • %s 导致本次core dump的信号
  • %t core dump的时间 (由1970年1月1日计起的秒数)
  • %h 主机名
  • %e 程序文件名

也可将“/proc/sys/kernel/core_uses_pid”设置为1,也会加上进程 ID。

GDB 调试 Core Dump 文件

当 Core Dump 之后,使用命令gdb program core来查看 Core 文件,其中 program 为可执行程序名,core 为生成的 core 文件名。

GDB 打开之后就可以执行bt或者where来查看最后 Core Dump 时的调用堆栈,问题点也很容易能够定位出来。

GDB 常用命令

启动方法

gdb program:program 也就是你的执行文件,一般在当前目录下。

gdb program core:用gdb同时调试一个运行程序和core文件,core是程序非法执行后core dump后产生的文件。

gdb program PID:可以指定这个程序运行时的进程ID,GDB 会自动 attach 上去并调试。

调试步进

  • continue 继续运行程序直到下一个断点
  • next 逐过程步进,不会进入子函数
  • setp 逐语句步进,会进入子函数
  • until 运行至当前语句块结束
  • finish 运行至函数结束并跳出,并打印函数的返回值

大部分命令可以只执行首字母,如上面标红的部分。

断点

添加断点:

  • break 在进入指定函数时停住
  • break 在指定行号停住。
  • break +/-offset 在当前行号的前面或后面的offset行停住。offiset为自然数。
  • break filename:linenum 在源文件filename的linenum行处停住。
  • break … if …可以是上述的参数,condition表示条件,在条件成立时停住。比如在循环境体中,可以设置break if i=100,表示当i为100时停住程序。

删除、禁用断点:

  • info breakpoints [n] 查看断点
  • delete 删除所有断点
  • delete breakpoint [n] 删除某个断点
  • disable breakpoint [n] 禁用某个断点
  • enable breakpoint [n] 使能某个断点

观察点

在变量读、写或变化时中断,这类方式常用来定位bug。

  • watch 变量发生变化时中断
  • rwatch 变量被读时中断
  • awatch 变量值被读或被写时中断

查看变量

  • print expr
  • print /f expr

/f是输出的格式,比如,如果要把表达式按16进制的格式输出,那么就是/x。

线程

如果你程序是多线程的话,你可以定义你的断点是否在所有的线程上,或是在某个特定的线程。GDB很容易帮你完成这一工作。

  • break linespec thread threadno
  • break linespec thread threadno if …

linespec 指定了断点设置在的源程序的行号。threadno指定了线程的 ID,注意,这个 ID 是 GDB 分配的,你可以通过info threads命令来查看正在运行程序中的线程信息。如果你不指定‘thread threadno ’则表示你的断点设在所有线程上面。你还可以为某线程指定断点条件。如:

1
(gdb) break frik.c:13 thread 28 if bartab > lim

其他

GDB 功能非常强大,这里仅列举了最常用的一小部分,其他可参考:Debugging with GDB

Cotin Yang wechat
欢迎订阅我的微信公众号 CotinDev
小小地鼓励一下吧~😘