vi/vim使用进阶: 在VIM中使用GDB调试 – 使用vimgdb

<< 返回vim使用进阶: 目录

本节所用命令的帮助入口:

:help vimgdb 

在UNIX系统最初设计时,有一个非常重要的思想:每个程序只实现单一的功能,通过管道等方式把多个程序连接起来,使之协同工作,以完成更强大的功能。程序只实现单一功能,一方面降低了程序的复杂性,另一方面,也让它专注于这一功能,把这个功能做到最好。就好像搭积木一样,每个积木只提供简单的功能,但不同的积木垒在一起,就能搭出大厦、汽车等等复杂的东西。

从UNIX系统(及其变种,包括Linux)的命令行就可以看出这一点,每个命令只专注于单一的功能,但通过管道、脚本等把这些命令揉合起来,就能完成复杂的任务。

vi/vim的设计也遵从这一思想,它只提供了文本编辑功能(与Emacs的大而全刚好相反),而且正如大家所看到的,它在这一领域做的是如此的出色。

也正因为如此,vim自身并不提供集成开发环境所需的全部功能(它也不准备这样做,vim只想成为一个通用的文本编辑器)。它把诸如编译、调试这样功能,交给更专业的工具去实现,而vim只提供与这些工具的接口。

我们在前面已经介绍过vim与编译器的接口(即quickfix),vim也提供了与调试器的接口,这一接口就是netbeans。除此之外,还可以给vim打一个补丁,以使其支持gdb调试器。

由于netbeans接口只能在gvim中使用,而使用vimgdb补丁,无论在终端的vim,还是gvim,都可以调试。所以我更喜欢打补丁的方式,我首先介绍这种方法。

打补丁的方式,需要重新编译vim,刚好借这个机会,介绍一下vim的编译方法。我只介绍Linux上编译方法,如果你想在windows上编译vim,可以参考这篇文档:Vim: Compiling HowTo: For Windows

[ 下载vim源代码 ]

首先我们需要下载vim的源码。到vim主页下载当前最新的vim 7.1的源代码,假设我们把代码放到~/install/目录,文件名为vim-7.1.tar.bz2。

[ 下载vimgdb补丁 ]

接下来,我们需要下载vimgdb补丁,下载页面在:

http://sourceforge.net/project/showfiles.php?group_id=111038&package_id=120238

在这里,选择vim 7.1的补丁,把它保存到~/install/vimgdb71-1.12.tar.gz。

[ 打补丁 ]

运行下面的命令,解压源码文件,并打上补丁:

cd ~/install/
tar xjf vim-7.1.tar.bz2
tar xzf vimgdb71-1.12.tar.gz
patch -d vim71 --backup -p0 < vimgdb/vim71.diff 

[ 定制vim的功能 ]

缺省的vim配置已经适合大多数人,但有些时候你可能需要一些额外的功能,这时就需要自己定制一下vim。定制vim很简单,进入~/install/vim71/src文件,编辑Makefile文件。这是一个注释很好的文档,根据注释来选择:

  • 如果你不想编译gvim,可以打开–disable-gui选项;
  • 如果你想把perl, python, tcl, ruby等接口编译进来的话,打开相应的选项,例如,我打开了–enable-tclinterp选项;
  • 如果你想在vim中使用cscope的话,打开–enable-cscope选项;
  • 我们刚才打的vimgdb补丁,自动在Makefile中加入了–enable-gdb选项;
  • 如果你希望在vim使用中文,使能–enable-multibyte–enable-xim选项;
  • 可以通过–with-features=XXX选项来选择所编译的vim特性集,缺省是–with-features=normal
  • 如果你没有root权限,可以把vim装在自己的home目录,这时需要打开prefix = $(HOME)选项;

编辑好此文件后,就可以编辑安装vim了。如果你需要更细致的定制vim,可以修改config.h文件,打开/关闭你想要的特性。

[ 编译安装 ]

编译和安装vim非常简单,使用下面两个命令:

make
make install 

你不需要手动运行./configure命令,make命令会自动调用configure命令。

上面的命令执行完后,vim就安装成功了。

我在编译时打开了”prefix = $(HOME)”选项,因此我的vim被安装在~/bin目录。这时需要修改一下PATH变量,以使其找到我编辑好的vim。在~/.bashrc文件中加入下面这两句话:

PATH=$HOME/bin:$PATH
export PATH 

退出再重新登录,现在再敲入vim命令,发现已经运行我们编译的vim了。

[ 安装vimgdb的runtime文件 ]

运行下面的命令,解压vimgdb的runtime文件到你的~/.vim/目录:

cd ~/install/vimgdb/
tar zxf vimgdb_runtime.tgz –C~/.vim/ 

现在启动vim,在vim中运行下面的命令以生成帮助文件索引:

:helptags ~/.vim/doc 

现在,你可以使用”:help vimgdb“命令查看vimgdb的帮助了。

至此,我们重新编译了vim,并为之打上了vimgdb补丁。下面我以一个例子来说明如何在vim中完成”编码—编译—调试”一条龙服务。

[ 在vim中调试 ]

首先确保你的计算机上安装了gdb ,vimgdb支持5.3以上的gdb版本,不过最好使用gdb 6.0以上的版本。

我使用下面这个简单的例子,来示例一下如何在vim中使用gdb调试。先来看示例代码:

文件~/tmp/sample.c内容如下,这是主程序,调用函数计算某数的阶乘并打印:

    
/* ~/tmp/sample.c */
#include <stdio.h>
extern int factor(int n, int *rt);

int main(int argc, char **argv)
{
    int i;
    int result = 1;

    for (i = 1; i < 6; i++)
    {
        factor(i, &result);
        printf("%d! = %d\n", i, result);
    }

    return 0;
}  

文件~/tmp/factor/factor.c内容如下,定义了子函数factor()。之所以把它放到子目录factor/,是为了演示vimgdb可以根据调试位置自动打开文件,不管该文件在哪个目录下:

    
/* ~/tmp/factor/factor.c */
int factor(int n, int *r)
{
    if (n <= 1)
        *r =  n;
    else
    {
        factor(n - 1, r);
        *r *= n;
    }

    return 0;
}  

Makefile文件,用来编译示例代码,最终生成的可执行文件名为sample。

    
# ~/tmp/Makefile
sample: sample.c factor/factor.c
gcc -g -Wall -o sample sample.c factor/factor.c  

假设vim的当前工作目录是~/tmp(使用”:cd ~/tmp“命令切换到此目录)。我们编辑完上面几个文件后,输入命令”:make“,vim就会根据Makefile文件进行编译。如果编译出错,vim会跳到第一个出错的位置,改完后,用”:cnext“命令跳到下一个错误,以此类推。这种开发方式被称为quickfix,我们已经在剑不离手 – quickfix一文中讲过,不再赘述。

现在,假设已经完成链接,生成了最终的sample文件,我们就可以进行调试了。

vimgdb补丁已经定义了一些键绑定,我们先加载这些绑定:

:run macros/gdb_mappings.vim 

加载后,一些按键就被定义为调试命令(vimgdb定义的键绑定见”:help gdb-mappings“)。按<F7>可以在按键的缺省定义和调试命令间切换。

好了,我们现在按空格键,在当前窗口下方会打开一个小窗口(command-line窗口),这就是vimgdb的命令窗口,可以在这个窗口中输入任何合法的gdb命令,输入的命令将被送到gdb执行。现在,我们在这个窗口中输入”gdb“,按回车后,command-line窗口自动关闭,而在当前窗口上方又打开一个窗口,这个窗口是gdb输出窗口。现在vim的窗口布局如下(我又按空格打开了command-line窗口):

小技巧: command-line窗口是一个特殊的窗口,在这种窗口中,你可以像编辑文本一样编辑命令,完成编辑后,按回车,就会执行此命令。你要重复执行某条命令,可以把光标移到该命令所在的行,然后按回车即可;你也可以对历史命令进行修改后再执行。详见”:help cmdline-window“。

接下来,在command-line窗口中输入以下命令:

cd ~/tmp
file sample 

这两条命令切换gdb的当前工作目录,并加载我们编译的sample程序准备调试。

现在使用vim的移动命令,把光标移动到sample.c的第7行和14行,按”CTRL-B“在这两处设置断点,然后按”R“,使gdb运行到我们设置的第一个断点处(“CTRL-B“和”R“都是gdb_mappings.vim定义的键绑定,下面介绍的其它调试命令相同)。现在vim看起来是这样:

断点所在的行被置以蓝色,并在行前显示标记1和2表明是第几个断点;程序当前运行到的行被置以黄色,行前以”=>”指示,表明这是程序执行的位置(显示的颜色用户可以调整)。

接下来,我们再按”C“,运行到第2个断点处,现在,我们输入下面的vim命令,在右下方分隔出一个名为gdb-variables的窗口:

:bel 20vsplit gdb-variables 

然后用”v“命令选中变量i,按”CTRL-P“命令,把变量i加入到监视窗口,用同样的方式把变量result也加入到监视窗口,这里可以从监视窗口中看到变量i和result的值。

现在我们按”S“步进到factor函数,vim会自动打开factor/factor.c文件并标明程序执行的位置。我们再把factor()函数中的变量n加入到监视窗口;然后按空格打开command-line窗口,输入下面的命令,把变量*r输入到变量窗口:

createvar *r 

现在,vim看起来是这样的:

现在,你可以用”S“、”CTRL-N“或”C“来继续执行,直至程序运行结束。

如果你是单步执行到程序结束,那么vim最后可能会打开一个汇编窗口。是的,vimgdb支持汇编级的调试。这里我们不用进行汇编级调试,忽略即可。

如果你发现程序有错误,那么可以按”Q“退出调试(gdb会提示是否退出,回答y即可),然后修改代码、编译、调试,直到最终完成。在修改代码时,你可能并不喜欢vimgdb的键映射(例如,它把CTRL-B映射为设置断点,而这个键又是常用的翻页功能),你可以按<F7>取消vimgdb的键映射,或者你直接修改gdb_mappings.vim文件中定义的映射。

看,vim + gdb调试是不是很简单?!

我们可以再定制一下,使调试更加方便。

打开~/.vim/macros/ gdb_mappings.vim文件,在”let s:gdb_k = 0“这一行下面加上这段内容:

" easwy add
if ! exists("g:vimgdb_debug_file")
    let g:vimgdb_debug_file = ""
elseif g:vimgdb_debug_file == ""
    call inputsave()
    let g:vimgdb_debug_file = input("File: ", "", "file")
    call inputrestore()
endif
call gdb("file " . g:vimgdb_debug_file)
" easwy end 

在”let s:gdb_k = 1“这一行下面加上这段内容:

" easwy add
call gdb("quit")
" end easwy 

注释掉最后一行的”call s:Toggle()“。

然后在你的vimrc中增加这段内容:

""""""""""""""""""""""""""""""
" vimgdb setting
""""""""""""""""""""""""""""""
let g:vimgdb_debug_file = ""
run macros/gdb_mappings.vim 

现在,在启动vim后,按<F7>,就进入调试模式以及设定调试的键映射。在第一次进入调试模式时,会提示你输入要调试的文件名,以后就不必再输入了。再按一次<F7>,就退出调试模式,取消调试的键映射。

利用vim的键映射(map)机制,你可以把你喜欢的gdb命令映射为vim的按键,方便多了。映射的例子可以参照~/.vim/macros/ gdb_mappings.vim。

再附上一张抓图,这是使用putty远程登录到linux上,在终端vim中进行调试。这也是我为什么喜欢vimgdb的原因,因为它可以在终端vim中调试,而clewn只支持gvim:

因为我不常使用gdb调试,所以本文仅举了个简单的例子,以抛砖引玉。欢迎大家共享自己的经验和心得。

我在文章vimgdb调试时的常见问题及解决中列出了一些常见问题及其解决方法,希望对大家有帮助。

最后,让我们感谢vimgdb作者xdegaye的辛勤劳动,我们后续文章会介绍pyclewn,这是vim与gdb结合的另外一种形式,它和vimgdb同属一个项目。

[参考文档]

<< 返回vim使用进阶: 目录

101 thoughts on “vi/vim使用进阶: 在VIM中使用GDB调试 – 使用vimgdb”

  1. 因为想用gdbvim所以需要手动编译。
    sudo make install 后没有出错,感觉是成功了。
    但是始终在vim下,跳不出gdb来。
    感觉是没安装到,于是把usr/share/vim 文件删除了。
    但终端还能用vim。
    然后再make install后发现没有生成usr/share/vim文件夹。
    那是不是没有安装成功???!

  2. /usr/local/bin/vim etc/vim /usr/share/vim 都有阿
    我是用ubuntu9.10, vim 7.2 gdbvim7.2
    始终还是挑不出gdbvim来。弄了好几天了

  3. 我把prefix =usr/share/vim/了
    用vi -v 时候出现的是中文介绍
    还有
    gdbprg=gdb_invocation
    设置这个时候说是未知选项?

  4. @zhongfeng
    看来你对linux很不熟悉,请设置一下PATH环境变量,使/usr/local/bin/vim最先被使用。
    或者直接用命令”/usr/local/bin/vim”来启动vim,启动后执行”:version”命令,看看是不是你自己编译的vim。

  5. :run macros/gdb_mappings.vim
    把这个加到.vimrc后,每次启动都会显示gdb映射成功的字样,感觉很烦,怎样去掉??之前好像搜到有人解决了,但没记下来

  6. 編譯完畢,執行./vim,確認是否可執行
    有些版本的GCC編譯後會不能執行
    若不能執行就需要以make CFLAGS=”-O3 -D_FORTIFY_SOURCE=1″編譯
    然後再安裝

  7. 我有一个问题,config.log 提示有以下错误(config.log的片段), 编译出来后在console下vim只能用createvar的方法添加变量,用v然后 CTRL + P会提示”Unable to create variable object”,

    conftest.c:9:28: error: ac_nonexistent.h: No such file or directory
    configure:3024: $? = 1
    configure: failed program was:
    | /* confdefs.h. */
    | #define PACKAGE_NAME “”
    | #define PACKAGE_TARNAME “”
    | #define PACKAGE_VERSION “”
    | #define PACKAGE_STRING “”
    | #define PACKAGE_BUGREPORT “”
    | #define UNIX 1
    | /* end confdefs.h. */
    | #include
    configure:3057: result: gcc -E
    configure:3086: gcc -E conftest.c
    configure:3093: $? = 0
    configure:3124: gcc -E conftest.c
    conftest.c:9:28: error: ac_nonexistent.h: No such file or directory
    configure:3131: $? = 1
    configure: failed program was:
    | /* confdefs.h. */
    | #define PACKAGE_NAME “”
    | #define PACKAGE_TARNAME “”
    | #define PACKAGE_VERSION “”
    | #define PACKAGE_STRING “”
    | #define PACKAGE_BUGREPORT “”
    | #define UNIX 1
    | /* end confdefs.h. */
    | #include
    configure:3169: checking for grep that handles long lines and -e
    configure:3229: result: /bin/grep
    configure:3234: checking for egrep
    configure:3298: result: /bin/grep -E
    configure:3312: checking for library containing strerror
    configure:3353: gcc -o conftest -g -O2 conftest.c >&5
    configure:3360: $? = 0
    configure:3391: result: none required
    configure:3402: checking for gawk
    configure:3418: found /usr/bin/gawk
    configure:3429: result: gawk
    configure:3442: checking for strip
    configure:3458: found /usr/bin/strip
    configure:3470: result: strip
    configure:3481: checking for ANSI C header files
    configure:3511: gcc -c -g -O2 conftest.c >&5
    configure:3518: $? = 0
    configure:3617: gcc -o conftest -g -O2 conftest.c >&5
    configure:3621: $? = 0
    configure:3627: ./conftest
    configure:3631: $? = 0
    configure:3649: result: yes
    configure:3659: checking for sys/wait.h that is POSIX.1 compatible
    configure:3695: gcc -c -g -O2 conftest.c >&5
    configure:3702: $? = 0
    configure:3717: result: yes
    configure:3756: checking for buggy tools…
    configure:3763: checking for BeOS
    configure:3769: result: no
    configure:3773: checking for QNX
    configure:3780: result: no
    configure:3784: checking for Darwin (Mac OS X)
    configure:4178: result: no
    configure:4186: checking –with-local-dir argument
    configure:4212: result: Defaulting to /usr/local
    configure:4237: checking –with-vim-name argument
    configure:4245: result: Defaulting to vim
    configure:4250: checking –with-ex-name argument
    configure:4258: result: Defaulting to ex
    configure:4263: checking –with-view-name argument
    configure:4271: result: Defaulting to view
    configure:4277: checking –with-global-runtime argument
    configure:4288: result: no
    configure:4293: checking –with-modified-by argument
    configure:4304: result: no
    configure:4309: checking if character set is EBCDIC
    configure:4338: gcc -c -g -O2 conftest.c >&5
    conftest.c: In function ‘main’:
    conftest.c:20: error: ‘make’ undeclared (first use in this function)
    conftest.c:20: error: (Each undeclared identifier is reported only once
    conftest.c:20: error: for each function it appears in.)
    conftest.c:20: error: expected ‘;’ before ‘an’
    configure:4345: $? = 1
    configure: failed program was:
    | /* confdefs.h. */
    | #define PACKAGE_NAME “”
    | #define PACKAGE_TARNAME “”
    | #define PACKAGE_VERSION “”
    | #define PACKAGE_STRING “”
    | #define PACKAGE_BUGREPORT “”
    | #define UNIX 1
    | #define STDC_HEADERS 1
    | #define HAVE_SYS_WAIT_H 1
    | /* end confdefs.h. */
    |
    | int
    | main ()
    | {
    | /* TryCompile function for CharSet.
    | Treat any failure as ASCII for compatibility with existing art.
    | Use compile-time rather than run-time tests for cross-compiler
    | tolerance. */
    | #if ‘0’!=240
    | make an error “Character set is not EBCDIC”
    | #endif
    | ;
    | return 0;
    | }

    用到confdefs.h的地方都提示错误,望赐教!

    而且在gvim根本没法加载macros/gdb_mappings.vim(没有任何提示),查看gvim后发现gvim没有被编译出来,是原来的gvim.

    我编译选项我uncomment了-enable-perlinterp, -enable-pythoninterp
    –enable-cscope, –enable-multibyte和–enable-xim选项

    系统
    Ubuntu 9.04
    GNU gdb 6.8
    vim 7.2
    vimgdb7.2
    GNOME

  8. 配置的时候最好–enable-gdb也加进去(就算打补丁的时候已经默认加了再加一次也没事吧~呵呵)
    同时也要–with-features=huge,不然语法高亮设置时会出错
    编译时:make CFLAGS=”-O2 -D_FORTiFY_SOURCE=1″
    这是解决我遇到的问题的三个提示,希望对后来者有帮助~ :)

  9. 你好 在使用vimgdb的时候,scanf输入不了,后使用tty /dev/pts/2,在另一个终端中提示
    “Failed to set controlling terminal: Operation not permitted”
    请问这个问题是怎么产生的,如何解决呢?

  10. @Easwy
    存在的。/dev/pts/2 是按你的文章中所说,先打开一个终端,再输入tty得到的。
    我也在CLI下测试了 打开了/dev/tty2,再在/dev/tty1上尝试使用vimgdb
    结果还是一样,在/dev/tty2上显示信息:
    warning: GDB: Failed to set controlling terminal: Operation not permitted

    后来我又试着直接用GDB调试,(/dev/pts/2也是存在的)发现也是一样的错误
    不论是用“gdb -tty=/dev/pts/2“
    还是先打开gdb 再执行命令 “tty /dev/pts/2”
    都得到这个错误。所以应该是GDB的问题吧。
    对这个问题
    有什么想法吗??

    系统 Slackware 13.1 桌面 GNOME(版本不太清楚)
    GDB 7.1 vim 7.2

  11. 您好,我在vim中执行:
    :run macros/gdb_mappings.vim
    没有什么反应阿
    按空格键也出不来调试窗口

    看了上面的解释我输入

    :set runtimepath

    显示為
    runtimepath=~/.vim,/usr/local/share/vim/vimfiles,/usr/local/share/vim/vim73,/u
    sr/local/share/vim/vimfiles/after,~/.vim/after

    怎么办阿
    谢谢

  12. es@es-laptop:~/Desktop/try$ find /usr/local/share/vim -name “gdb_mappings.vim”
    /usr/local/share/vim/vim73/macros/gdb_mappings.vim

    有gdb_mappings.vim啊

  13. 在Fedora、Red Hat、Ubuntu上都成功编译了打了vimgdb补丁的vim源代码。
    在Fedora、Red Hat能够正常地在vim中使用gdb。但是,在Ubuntu中,一旦在底行键入“:run macros/gdb_mappings.vim”,vim立刻崩溃。出现错误提示:

    段错误(吐核)
    已放弃

  14. 博主您好,本人刚学vim,我在使用vimgdb调试我的项目的时候发现一个问题,就是我的makefile里面如果加了-O3标志,gdb单步跟踪的时候会出现一些莫名奇妙的跳转,后来尝试把O3去掉就恢复正常了。我用的是C++,vim 7.3和7.2都用过,都有这个问题。可是去掉O3貌似会降低一些性能吧?不知能博主有没有遇到过类似的情况?有没有解决方案?多谢

  15. 请教一个问题, 我在使用vimgdb 调试程序的时候, 可能需要像在gdb里面可以随时随地的 用 ctrl+c 中断程序让程序停止下来,查看代码内存什么的, 可在vimgdb里我尝试了一些办法依然没有实现, 只有拙略的让程序自动的到设置的断点处停止, 请问怎么按键映射里设置,我自己设置了按键映射没起效,请教!

  16. 我的问题自己解决了,自己试出来了,
    步骤是:
    按空格出现 [Command Line] 后
    Ctrl + c 按下 2次 c 然后就好了
    gdb 窗口出现 Program received signal SIGINT, Interrupt.
    好了解决。

  17. 我按照方法编译出现这个问题:
    方法:
    tar xjf vim-7.4.tar.bz2
    tar xzf vimgdb72-1.14.tar.gz

    patch -d vim74 –backup -p0 < vimgdb/vim72.diff

    cd vim74/src
    make make vim
    make install install vim (may require root privileges)
    make出现的问题:

    make: *** 没有规则可以创建“vim”需要的目标“@GDB_OBJ@”。 停止。

    系统是Cent OS6.5,VIM版本是7.4,在vim74/src的Makefile文件中打开了
    –enable-pythoninterp
    –enable-python3interp
    –enable-multibyte
    –enbale-cscope
    这几个选项。网上说是没有执行configure的问题,但是vimgdb的说明中要求最好不要这样执行的。

  18. 楼主你好,
    我在这儿下载的https://github.com/larrupingpig/vimgdb-for-vim7.4的vimgdb7.4的zip包,解压后按照这个网站下面给出的提示,但是报错:
    gcc -c -I. -Iproto -DHAVE_CONFIG_H -DFEAT_GUI_GTK -pthread -D_REENTRANT -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/directfb -I/usr/include/libpng12 -O6 -o objects/buffer.o buffer.c
    In file included from vim.h:1943,
    from buffer.c:28:
    proto.h:263:21: error: gdb.pro: No such file or directory

    弄了一天了,崩溃,求解决。

    也下载过7.3版本的vimgdb和vim,按照步骤,还是不行,提示缺少头文件,安装了几个看起来比较像的库,还是没解决,郁闷之极。

发表评论

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