1 引言
Emacs除了具有强大的编辑功能,还可以作为调试工具gdb的前端,对程序进行调试。使用Emacs进行调试,可以将程序的编写与调试统一到Emacs中,并利用Emacs强大的功能辅助调试,是将Emacs作为IDE使用的一项必备功能。
本文假定读者具有基本的程序调试知识,希望知道在Emacs下进行基本调试的对应操作。水平有限,欢迎拍砖。
3 开始:开启Emacs的调试模式GUD
3.1 运行gdb
在编译好程序后,就可以开始调试了。直接运行gdb命令M-x gdb RET 在minibuffer中会出现需要执行的gdb命令。例如:gdb –annotate=3 prog 如果当前目录下有可执行文件(通常恰好是需要调试的文件),gdb会在其后自动补上可执行文件,否则需要在minibuffer中补上要调试的程序文件 名。
继续回车,Emacs的GUD(Grand Unified Debugger)就会关联到gdb并加载要调试的程序了。
4 调试:设置断点,控制程序流程
4.1 设置、删除断点
首先将断点设置在要调试的地方。有两种方法:
第一种,在要设置断点的行左边的fringe上单击一下(就是文本左边与滚动条之间空出的那一块)。隐藏了fringe的朋友可以M-x fringe-mode显示它。
第二种,使用默认快捷键C-x C-a C-b, 或者 C-x <SPC>。它们都关联到命令gud-break。
无论使用哪种方法,fringe上都会在设置了断点的行上显示一个红点,表示这行设了断点:
同时,在断点buffer中也会显示已有的断点信息:
要删除断点,同样有两种对应的方法:在fringe的断点上单击一下,或者使用快捷键C-x C-a C-d(对应命令gud-remove)。
可以在断点buffer上单击某个断点切换到断点所在位置。将光标移动到断点处回车也有同样的效果。
在断点buffer上按空格键可以切换断点的激活和禁用状态。
4.3 单步执行、运行到光标处
在调试中最常用的功能就是单步执行了。单步执行有两种:将函数调用作为一条语句执行(Next)和遇到函数时进入函数中进行调试(Step)。
要使用第一种方式,默认快捷键是C-x C-a C-n,对应命令为gud-next。也可以单击工具栏上的 。
第二种方式的默认快捷键是C-x C-a C-s,对应命令为gud-step。也可以单击工具栏上的 。
如果想跳出当前函数,可以使用命令gud-finish,默认快捷键为C-x C-a C-f,工具栏上有 可用。
在Emacs中还可以运行到光标所在的行。使用命令gud-until即可,默认快捷键为C-x C-a C-u。1
也可以直接把当前语句指示器拖到任意一行,程序会运行到那一行再停下来。
5 察看变量的值
调试的过程中免不了要查看变更的值。Emacs提供了方便地功能让我们查看变量的值。
5.1 本地变量buffer
如果打开了gdb-many-windows,在右上角会显示Locals buffer,其中显示了当前局部变量的值。如果显示的是寄存器(Register)buffer,单击左边的Locals就可以切换到Locals buffer了。在其中可以方便地观察到各变量的值。
如果没有打开gdb-many-windows,也可以使用gdb-display-locals-buffer来显示该buffer。
5.2 察看变量值
遇到一些Locals里没有显示的变量,或者比较复杂的结构,就需要用到观察变量的功能了。
将光标停留在要观察的变量上,执行命令gud-watch,可以将变量加入观察列表中。默认的快捷键是C-x C-a C-w。也可以使用工具栏上的 。
被观察的变量将在Speedbar中显示。对于复杂结构,可以单击Speedbar上的+号将其展开或收缩。在+号上按空格键也有相同的效果。2
有时候Emacs观察的变量不是你所想要的,一般是a->b这类的情况。这时可以将要观察的部分选中,再使用上述方法即可。
7 按键绑定
说实话,gud自带的按键绑定实在是麻烦,使用一个功能要三次组合键才行,小姆指按Ctrl都按酸了。所以一般将常用的按键绑定在方便的位置,这样才能有和另的IDE一样的快感。
以下是将F5、F7、F8分别绑定到gud-go、gud-step和gud-next的代码:
1 2 3 4 | (add-hook 'gdb-mode-hook '(lambda () (define-key c-mode-base-map [(f5)] 'gud-go) (define-key c-mode-base-map [(f7)] 'gud-step) (define-key c-mode-base-map [(f8)] 'gud-next))) |
之所以绑定到c-mode-base-map上,是因为我基本上在代码buffer中调试。如果要在gdb-buffer中使用的话,需要使用gud-mode-map。如果想在所有buffer上使用的话,可以绑定到全局按键中:
(global-set-key [(f5)] 'gud-go) |
8 结尾
有了调试功能,Emacs作为一个IDE才算是完整了。本文介绍了在Emacs下使用gdb调试的基本方法,Emacs的调试功能还远不止这些,进一步学习可参阅 Emacs Manual 的 Debuggers 一节。
由于我也是边学边写,一定有许多不足或者错误,还请各位多多指教。