首页 > IDE, 中级 > 在Emacs中使用gdb调试程序

在Emacs中使用gdb调试程序

2010年3月29日 ahei 发表评论 阅读评论

作者: Tiger Soldier

1 引言

Emacs除了具有强大的编辑功能,还可以作为调试工具gdb的前端,对程序进行调试。使用Emacs进行调试,可以将程序的编写与调试统一到Emacs中,并利用Emacs强大的功能辅助调试,是将Emacs作为IDE使用的一项必备功能。

本文假定读者具有基本的程序调试知识,希望知道在Emacs下进行基本调试的对应操作。水平有限,欢迎拍砖。

2 准备工作:将调试信息编译在程序中

要使程序能被gdb调试,需要在编译时加入调试所需的信息。如果使用gcc/g++进行编译,需要使用参数-g,如:

gcc prog.c -g -o prog

如果使用 ./confiugre && make 的编译流程,可以将使用如下方式引入-g参数:

1
2
CFLAGS="-g" ./configure
make

注意:不要加入任何优化参数(例如-O、-O2),不然调试时会有很灵异的现象发生……

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并加载要调试的程序了。

3.2 gdb界面

启动gdb后,Emacs的界面会变成下面两种之一:

GDB单窗格模式

GDB多窗格模式

可以通过gdb-many-windows来切换这两种界面布局。

如果界面被打乱了(例如,在minibuffer中使用补全,查看帮助,重新编译程序),可以使用gdb-restore-windows来恢复界面布局。

3.3 小结

命令 功能
gdb 启动gdb进行调试
gdb-many-windows 切换单窗格/多窗格模式
gdb-restore-windows 恢复窗格布局

接下来就要开始调试程序了。

4 调试:设置断点,控制程序流程

4.1 设置、删除断点

首先将断点设置在要调试的地方。有两种方法:

第一种,在要设置断点的行左边的fringe上单击一下(就是文本左边与滚动条之间空出的那一块)。隐藏了fringe的朋友可以M-x fringe-mode显示它。

第二种,使用默认快捷键C-x C-a C-b, 或者 C-x <SPC>。它们都关联到命令gud-break。

无论使用哪种方法,fringe上都会在设置了断点的行上显示一个红点,表示这行设了断点:

同时,在断点buffer中也会显示已有的断点信息:

断点buffer

要删除断点,同样有两种对应的方法:在fringe的断点上单击一下,或者使用快捷键C-x C-a C-d(对应命令gud-remove)。

可以在断点buffer上单击某个断点切换到断点所在位置。将光标移动到断点处回车也有同样的效果。

在断点buffer上按空格键可以切换断点的激活和禁用状态。

4.2 运行程序

设置好断点后就可以运行程序了。单击工具栏上的运行就开始运行了。也可以使用gud-go命令来运行。奇怪的是没有任何默认快捷键绑定。

当程序运行到断点时,程序会在断点处停下来,并自动打开停下的语句所在的代码文件。同时在fringe上在停下的语句处有三角形的指示器。

现在,我们来一步步运行程序。

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

也可以直接把当前语句指示器拖到任意一行,程序会运行到那一行再停下来。

4.4 继续运行程序

在程序中断后要继续运行程序,依然是使用gud-go命令或 继续运行 ,也可以使用命令gud-cont,对应快捷键为C-x C-a C-r。

4.5 小结

功能 命令 默认快捷键
添加断点 gud-break C-x C-a C-b 或 C-x <SPC>
删除断点 gud-remove C-x C-a C-d
运行/继续程序 gud-go
单步执行,无视函数 gud-next C-x C-a C-n
单步执行,进入函数 gud-step C-x C-a C-s
跳出当前函数 gud-finish C-x C-a C-f
运行到光标所在语句 gud-until C-x C-a C-u
继续运行程序 gud-cont C-x C-a C-r

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这类的情况。这时可以将要观察的部分选中,再使用上述方法即可。

5.3 用工具提示显示变量值

可以用gud-tooltip-mode开启或关闭工具提示。开启后将鼠标指针停留在变量名上时将在工具提示中显示变量的值。

5.4 小结

功能 命令 默认快捷键
观察变量 gud-watch C-x C-a C-w
展开/收缩变量 <SPC>
开启/关闭工具提示 gud-tooltip-mode

6 输入输出

如果程序需要与标准输入/输出交互,那么你很可能需要用到下面要介绍的功能。

6.1 单独的IO buffer

默认来说,程序的输入输出是在gdb buffer里显示的。这样输出信息和gdb信息混合在一起,阅读起来非常不便。这时候,你需要把输入输出单独显示在一个buffer里,方便查看。

使用gdb-use-separate-io-buffer,可以在程序代码buffer右侧新建一个IO buffer,程序对标准输入输出的操作都会重定向到这里。再执行一次该命令则会隐藏。

6.2 输入数据

需要输入数据的时候,只需要在IO buffer中输入数据回车即可。已经输入的数据会被加粗,以和输出信息区分开来。

6.3 重定向到文件

有时候我们已经准备好了用于输入的数据在文件中,以避免调试时烦琐的输入。这时候就需要在调试时进行输入输出重定向了。

要进行重定向,只能使用gdb自带的功能。在gdb buffer中输入 run < data.in > data.out 就可以将标准输入重定向到data.in,将标准输出重定向到data.out了。

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 ManualDebuggers 一节。

由于我也是边学边写,一定有许多不足或者错误,还请各位多多指教。

Footnotes:

1 注:我在使用时只有光标所在的行在当前行之后并且位于同一函数内才行,否则会跳到很奇怪的地方,还请高手指教。

2 我在使用过程中经常出现展开没反应,或者加入新元素后才展开,运行几步才展开的情况,求高人讲解。

分享家:Addthis中国
GD Star Rating
loading...
在Emacs中使用gdb调试程序, 8.9 out of 10 based on 24 ratings 标签:ann, CEDET, ctrl, ede, Emacs, gdb, gud, IDE, lambda, org, screenshot, speedbar, text, windows, 光标, 工具栏, 补全, 配色, 鼠标

相关日志

分类: IDE, 中级
  1. tmpistemp
    2010年3月29日03:06 | #1

    我订阅了,不错.

    [回复]

    ahei 回复:

    @tmpistemp, 哈哈,才订阅阿

    [回复]

    tmpistemp 回复:

    @ahei, 最近谷歌风言风语,搞的我想换rss阅读器了,想把谷歌换掉,换有道好还是鲜果好呢感觉?

    [回复]

    ahei 回复:

    @tmpistemp, google最好,不用换。

    [回复]

    tmpistemp 回复:

    @ahei, 怕谷歌挂掉.

    [回复]

    ahei 回复:

    @tmpistemp, 别怕别怕,挂了翻墙呗,而且换feed也容易。

    [回复]

    tmpistemp 回复:

    @ahei, 唉,cn域名挂了,dns转出去,everydns又被出售了,现在谷歌要是再挂了,就不想让人活了.

    [回复]

  2. 匿名
    2010年3月29日06:27 | #2

    svn checkout http://dea.googlecode.com/svn/trunk dea-read-only
    svn: 方法 OPTIONS 失败于 “http://dea.googlecode.com/svn/trunk”: 不能读状态行: 连接被服务器关闭 (http://dea.googlecode.com)
    最近这几天发现老有这样的问题,在ubuntu9.10下,svn是最新sudo apt-get install subversion 安装的。

    [回复]

    ahei 回复:

    @, 我的可以阿,你有没有用什么代理?有时候我加代理了也不能checkout,或者你直接下载tar包。

    [回复]

    匿名 回复:

    @ahei, 我什么代理都没加,好像就那台虚拟机里的会出现这样
    的问题。还有我看到你说:
    如果你使用DEA启动Emacs后出现如下错误:
    error: Font `fontset-courier’ is not defined
    打开你下载后的DEA里面的.emacs文件,搜索到如下语句:
    (when (and window-system is-after-emacs-23)
    (load “my-fontset-win”)
    (if mswin
    (huangq-fontset-courier 17)
    ;; (huangq-fontset-dejavu 17)))
    (huangq-fontset-fixedsys 17)))

    然后把这段语句注释掉,然后执行
    ./install.emacs.sh

    用emacs修改自己 的.emacs不行,要用gedit修改才奏效

    [回复]

    ahei 回复:

    @, 我是说修改你下载或checkout后那个目录下的.emacs,而不是你的home目录下的emacs,因为./install.emacs.sh会覆盖你home目录下的.emacs,所以如果你执行了./update.sh或者./install.emacs.sh的话,你随便用什么软件修改你home目录下的.emacs也没用的。你可以看看我那个几个脚本,很简单的。

    [回复]

    匿名 回复:

    @ahei, 8-O 没看清楚,汗……

    [回复]

  3. tangboyun
    2010年3月29日06:45 | #3

    :mrgreen: 我也是前几天才顺藤摸瓜找到这里的,好文章真多,对我帮助挺大的。

    [回复]

    ahei 回复:

    @tangboyun, 呵呵,希望本站能继续对你起到帮助。

    [回复]

  4. **
    2010年3月29日09:18 | #4

    用emacs调试程序其实一直都觉得不太顺手,可能是以前用vs系列调试c#的时候被gui宠坏了。。。

    于是导致了现在写c程序能不用gdb就尽量不用,大部分都console output解决……

    虽然知道gdb这东西很强大,但是用起来还真有点难度……额

    [回复]

    ahei 回复:

    @**, 哈哈,那看来是被vs害惨了。gdb实在是太强大了,再配上emacs用起来就是非常的方便。而且gdb的s和n命令非常的方便,根本都不需要定制那些Fn快捷键的。

    [回复]

    Tiger Soldier 回复:

    @ahei, 有道理,我之前是直接在source buffer里调试,没想过直接在gdb buffer里调试。还是Windows下调试的那种思维呀

    [回复]

    ahei 回复:

    呵呵,gdb下如果你没有输入任何命令直接回车的话,会执行上次的命令,所以单步执行的时候,只需要第一次按n,以后不停的按回车键就可以了,也只需要按一个键,而且还比Fn键方便,不过那些Fn键确实可以作为辅助,毕竟有时候调试代码要跑到代码的buffer里面.相辅相成,更加强大.

    [回复]

    ** 回复:

    @ahei, 其实只是觉得观察变量不太好操作而已,估计是自己不够熟悉。看来还是习惯才是最重要的。就像刚学时候那样上下左右移动个光标都要想一下快捷键是啥……

    [回复]

    ahei 回复:

    @**, 看变量的话p就非常方便啦,再加上文中作者所说的查看变量的方法就更方便了,呵呵,多习惯一下。

    [回复]

  5. deadleon
    2010年5月30日04:04 | #5

    有个问题,多个c文件时,似乎emacs中的gdb只打开main.c ,打开其他c文件时emacs会变成编辑模式。

    [回复]

    TigerSoldier 回复:

    @deadleon, 这个问题也困扰过我,有时就是重启emacs之后就好了。还希望有高人解答吧

    [回复]

    deadleon 回复:

    @TigerSoldier, 很痛苦,没搞清楚是什么问题,
    本来是用emacs的,后来改成ide了

    [回复]

    ahei 回复:

    @deadleon, 直接用命令吧,非常方便,要习惯用命令,都是单字母的,多方便啊,而且还有回车就默认使用上个命令,非常之方便.

    [回复]

  6. deadleon
    2010年6月1日23:59 | #6

    多个源文件时你就感觉很痛苦了,少一点的还可以

    [回复]

    ahei 回复:

    我还是调试过不少大项目的,gdb会帮你找文件的,命令特别方便

    [回复]

  7. 匿名
    2010年6月13日01:24 | #7

    匿名 :
    svn checkout http://dea.googlecode.com/svn/trunk dea-read-only
    svn: 方法 OPTIONS 失败于 “http://dea.googlecode.com/svn/trunk”: 不能读状态行: 连接被服务器关闭 (http://dea.googlecode.com)
    最近这几天发现老有这样的问题,在ubuntu9.10下,svn是最新sudo apt-get install subversion 安装的。
    [回复]ahei 回复:三月 29th, 2010 at 6:33 上午@, 我的可以阿,你有没有用什么代理?有时候我加代理了也不能checkout,或者你直接下载tar包。
    [回复]匿名 回复:三月 29th, 2010 at 7:00 上午@ahei, 我什么代理都没加,好像就那台虚拟机里的会出现这样
    的问题。还有我看到你说:
    如果你使用DEA启动Emacs后出现如下错误:
    error: Font `fontset-courier’ is not defined
    打开你下载后的DEA里面的.emacs文件,搜索到如下语句:
    (when (and window-system is-after-emacs-23)
    (load “my-fontset-win”)
    (if mswin
    (huangq-fontset-courier 17)
    ;; (huangq-fontset-dejavu 17)))
    (huangq-fontset-fixedsys 17)))
    然后把这段语句注释掉,然后执行
    ./install.emacs.sh
    用emacs修改自己 的.emacs不行,要用gedit修改才奏效
    [回复]ahei 回复:三月 29th, 2010 at 7:06 上午@, 我是说修改你下载或checkout后那个目录下的.emacs,而不是你的home目录下的emacs,因为./install.emacs.sh会覆盖你home目录下的.emacs,所以如果你执行了./update.sh或者./install.emacs.sh的话,你随便用什么软件修改你home目录下的.emacs也没用的。你可以看看我那个几个脚本,很简单的。
    [回复]匿名 回复:三月 29th, 2010 at 7:18 上午@ahei, 没看清楚,汗……
    [回复]

    请问你是怎么解决的,我也出现了这个问题,请赐教!谢谢…

    [回复]

  8. sunweik
    2010年7月21日07:08 | #8

    gdb一直有一个最大的问题:
    比如在一次运行中disp了一些变量;然后重新编译了程序;gdb reload a.out之后,disp的这些变量就消失了,要重新disp它们非常麻烦。
    不知道哪位大侠知道有什么方法象save breakpoint一样可以保存起来disp的list?

    [回复]

  9. shelton
    2010年10月11日21:13 | #9

    Excellent!

    [回复]

  10. 2010年10月13日12:21 | #10

    @sunweik 我也常有此疑惑

    [回复]

评论分页
1 2 3 41056
  1. 2010年3月29日02:24 | #1
  2. 2012年5月12日23:07 | #2
  3. 2012年11月3日15:59 | #3
  4. 2014年6月22日13:28 | #4
:wink: :-| :-x :twisted: :) 8-O :( :roll: :-P :oops: :-o :mrgreen: :lol: :idea: :-D :evil: :cry: 8) :arrow: :-? :?: :!: