how to debug with some tips or tools

调试-linux程序设计

clip_image001

错误查找及纠正

有几种原因会造成程序的缺陷,针对每种原因,都有一些建议的方法来查找和纠正。比如功能定义错误,设计规划错误和代码编写错误

clip_image003

程序调试的5个阶段

clip_image005

使用printf来排错

       相信这个方法是N多人使用的方法

使用-Wall选项来排错

       在使用gcc编译的时候加上-Wall选项,可以提前发现很多的warnings

注释法

       将怀疑有错的程序块注释起来,查看一下结果,如此反复即可。

使用内置宏__FILE__

       灵活使用内置宏__LINE__,__FILE__,__DATE____TIME可以很快速地定位问题所在。

使用assert断言来预防错误的发生

       诸如分母不能为0的情况。

专业级别的gdb调试

       关于gdb的调试,参考:

clip_image006 clip_image008 clip_image010

静态分析调试工具

ctags

       参考:http://ctags.sourceforge.net/

       相信使用过vim的童鞋都晓得这个工具,ctagsGenerate tag files for source code)是vim下方便代码阅读的工具。尽管ctags也可以支持其它编辑器,但是它正式支持的只有VIM。并且VIM中已经默认安装了Ctags,它可以帮助程序员很容易地浏览源代码。

ctags 最先是用来生成C代码的tags文件,后来扩展成可以生成各类语言的tags, 有些语言也有专有的tags生成工具(比如javajtags, python ptags)

clip_image012

cxref

参考:http://www.gedanken.demon.co.uk/cxref/

Cxref是一款在LaTeXHTMLRTFSGML中将C代码生成文件的程序,包括从C程序源代码的交叉引用。它用于ANSI C,包含大多数gcc扩展,可以从代码中的注释进行生成适当格式的程序文档,交叉引用来自于代码本身并不需要额外的工作。

clip_image014

cflow

参考:http://www.gnu.org/software/cflow/

GNU cflow analyzes a collection of C source files and prints a graph, charting control flow within the program.

GNU cflow is able to produce both direct and inverted flowgraphs for C sources. Optionally a cross-reference listing can be generated. Two output formats are implemented: POSIX and GNU (extended).

Input files can optionally be preprocessed before analyzing.

The package also provides Emacs major mode for examining the produced flowcharts in Emacs.

clip_image016

动态分析调试工具

gprof

gprofGNU profiler工具。可以显示程序运行的“flat profile”,包括每个函数的调用次数,每个函数消耗的处理器时间。也可以显示调用图,包括函数的调用关系,每个函数调用花费了多少时间。还可以显示注释的源代码,是程序源代码的一个复本,标记有程序中每行代码的执行次数。

gprof编译程序


在编译或链接源程序的时候在编译器的命令行参数中加入“-pg”选项,编译时编译器会自动在目标代码中插入用于性能测试的代码片断,这些代码在程序在运行时采集并记录函数的调用关系和调用次数,以及采集并记录函数自身执行时间和子函数的调用时间,程序运行结束后,会在程序退出的路径下生成一个gmon.out文件。这个文件就是记录并保存下来的监控数据。可以通过命令行方式的gprof或图形化的Kprof来解读这些数据并对程序的性能进行分析。另外,如果想查看库函数的profiling,需要在编译是再加入“-lc_p”编译参数代替“-lc”编译参数,这样程序会链接libc_p.a库,才可以产生库函数的profiling信息。如果想执行一行一行的profiling,还需要加入“-g”编译参数。
例如如下命令行:
gcc -Wall -g -pg -lc_p example.c -o example

clip_image018

工具lint

lint是最著名的C语言工具之一,是由贝尔实验室SteveJohnson1979PCC(PortableC Compiler)基础上开发的静态代码分析,一般由UNIX系统提供。与大多数C语言编译器相比,lint可以对程序进行更加广泛的错误分析,是一种更加严密的编译工具。最初,lint这个工具用来扫描C源文件并对源程序中不可移植的代码提出警告。但是现在大多数lint实用程序已经变得更加严密,它不但可以检查出可移植性问题,而且可以检查出那些虽然可移植并且完全合乎语法但却很可能是错误的特性。

随着历史的推移,Lint后来形成了一系列的工具,包括PC-Lint/FlexeLint(Gimpel),LintPlus(Cleanscape)以及Splint

clip_image019

内存调试工具ElectricFence

clip_image020

参考:http://directory.fsf.org/wiki/Electric_Fence

       实际运行环境中经常比较困扰的问题是内存产生轻微越界,但是并没有立刻产生问题, 给调查带来很大难度。

如果程序问题调查没有头绪,可以借助 Electric Fence (简称 Efence )工具检查内存问题并产生 CORE 文件,比较精确的定位问题场所。

       在发生如下问题的情况下此工具会转储 CORE

1 )动态分配内存边界外的读写操作

2 )访问已经 free 的内存

3 free 的地址不是 malloc() 分配的

Valgrind

       参考:http://valgrind.org/

Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具。

clip_image021

the use of ctag in vim

vim-ctag的使用

clip_image002

ctags

clip_image003

首先需要安装ctags,可以使用apt-getyum或者源码安装。

Ctags是一个用于从程序源代码树产生索引文件(或tag文件),从而便于文本编辑器来实现快速定位的实用工具。在产生的tag文件中,每一个tag的入口指向了一个编程语言的对象。这个对象可以是变量定义、函数、类或其他的物件。

Ctags是开放源代码的程序。支持下列的编程语言:汇编,AWK, ASP, BETA, Bourne/Korn/Zsh Shell, C, C++, COBOL, Eiffel, Fortran, Java, Lisp, Lua, Make, Pascal, Perl, PHP, Python, REXX, Ruby, S-Lang, Scheme, Tcl, Vim, and YACC

支持Ctags产生的tag文件的编辑器以及编辑器插件包括:VimVileLemmy,等等。

步骤

进入需要创建索引文件的文件夹,执行ctags *.c即可将所有的c源文件创建索引文件tags

       可以通过cat tags来查看一下tags的内容。

      

导航到function的方法:

l  可以使用:ta function直接跳转到function

l  当光标为function上时,使用CTRL+]也可以直接跳转到function

 

返回原来的使用它CTRL+T即可。

 

Ta跳转也支持正则表达式,比如:ta /^get就会搜索以get开始的函数。

 

Ctagsvim命令及描述

:ts

显示tag list

:tn

跳到list中的下一个

:tp

跳到list中的上一个

:tf

跳到list中的第一个

:tl

跳到list中的最后一个

clip_image005

 

 

 

也可以通过taglis插件实现如下效果,直接媲美IDE,哈哈。

具体参考:http://guoshaoguang.com/blog/2011/11/09/%e7%8e%a9%e8%bd%acvim%e4%b9%8bubuntu%e4%b8%8b%e5%88%9b%e5%bb%bavimtaglistcscopectags%e7%bb%84%e5%90%88%e7%bc%96%e8%be%91%e5%99%a8/

clip_image007

玩转vim之Ubuntu下创建vim+Taglist+cscope+ctags组合编辑器

玩转vimUbuntu下创建vim+Taglist+cscope+ctags组合编辑器

各个插件更详细的信息可以参考各个插件在本blog的文章。

Referhttp://blog.csdn.net/longerzone/article/details/7789581

Ubuntu给我们安装软件提供了很大的便利,比如说,安装vim,我们可以直接使用“sudo apt-get install vim”即可安装!

同样,cscopectags也可以使用相同方法安装,这是多么畅快淋漓啊!谢谢Ubuntu给我们用户如此便利!

对于Taglist使用这个方法安装不了,我们需要先下载,然后安装完成:

首先上网下载Taglist插件,下载完成后解压,再将文件下的taglist.vim使用cp命令拷贝到HOME/.vim/plugin文件夹下(cp -r taglist.vim ~/.vim/plugin)

 

这样,vim+Taglist+cscope+ctags四种工具我们是创建好了,但是如何使用呢?

 

vim是一个非常好用的编辑工具,以下介绍几个常用的底行模式命令:

1. 设置缩进

     :set    smartindent      // 设置缩进

      :set smartindent shiftwidth=4      // C语言自动缩进,缩进值为4个字符宽度

2. 显示光标行列信息

      :set ruler             // 显示光标信息(右下角)

3. 查看制表符

      :set list               // 显示制表符,以^符号显示制表符的位置

4. 查看行数信息

     :set number        //显示行号(左边)

5. 关键字高亮

    :syntax on                  //关键字高亮

6多文件编辑 ,在编写程序时有可能需要同时编辑多个文件,在这种情况下,需要如下设置

    : split two.c             //  多文件编辑

 

当然,如果不嫌麻烦,可以在每次打开Vim时 输入如上命令,如我经常用的是:set number :set ruler :syntax on :set smartindent 命令,如果将平时在底行模式下输入的命令直接写入配置文件,则以后使用Vim时不用再次输入这些命令。

首先,试着在Vi的底行模式下输入如下命令,如果不支持的话,去下载一个Vim的全版本,sudo apt-get install vim-full

以下是修改配置文件的方法:

1. 找到Vimrc文件。

2)查看文件的权限:

zhouyl@ubuntu:~$ cd /etc/vim
zhouyl@ubuntu:/etc/vim$ ls
vimrc  vimrc~  vimrc.tiny
zhouyl@ubuntu:/etc/vim$ ls -l vimrc
-rw-r–r– 1 root root 3449  9
11 17:30 vimrc

3)如果没有写权限的话,修改权限,使我们可以修改该配置文件

   sudo chmod a+w vimrc
 
4)根据个人需要将上诉命令写入配置文件
      
比如,我个人的设置是:
syntax on , set ruler ,set number , set smartindent shiftwidth=4

下面贴上我的vimrc文件的配置信息:

  1. set number   
  2.    
  3. 检测文件的类型   
  4. filetype on   
  5.  
  6. 记录历史的行数   
  7. set history=1000   
  8.  
  9. 自动对齐   
  10. set autoindent   
  11. set cindent   
  12.    
  13. 智能选择对齐方式   
  14. set smartindent   
  15.    
  16. “tab4个空格   
  17. set tabstop=4   
  18.    
  19. 当前行之间交错时使用4个空格   
  20. set shiftwidth=4   
  21.    
  22. 设置匹配模式,输入做括号会出现右括号   
  23. set showmatch   
  24.  
  25. 编辑时显示光标状态   
  26. set ruler   
  27.  
  28.  
  29. 快速匹配   
  30. set incsearch 
  31.  
  32. 修改文件自动备份   
  33. if has(“vms”) 
  34.     set nobackup 
  35. else 
  36.     set backup 
  37. endif 
  38.  
  39. “””””””””””””设置开启ctags”””””””””””””  
  40. set tags=/home/zhouyl/linux-3.4.7/tags;”在这设置ctags -R 后生成的tags文件所在目录,下面有介绍,如果需要配置多个tags。只需如下再添加即可 
  41. set tags=/home/zhouyl/rap/libpcap-1.3.0/tags; 
  42. set autochdir 
  43.  
  44.  
  45. “””””””””””””””””Taglist设置“””””””””””””””””        
  46. “”let Tlist_Auto_Open = 1             
  47. let Tlist_Ctags_Cmd = ‘/usr/bin/ctags’ 
  48. let Tlist_Show_One_File = 1 
  49. let Tlist_Exit_OnlyWindow = 1 
  50.  
  51.  
  52. “”””””””””””””””””””””cscope设置“”””””””””””””””””   
  53. set cscopequickfix=s-,c-,d-,i-,t-,e- 
  54. if has(“cscope”) 
  55. set csprg=/usr/bin/cscope 
  56. set csto=1 
  57. set cst 
  58. set nocsverb 
  59. ” add any database in current directory   
  60. if filereadable(“cscope.out”) 
  61. cs add cscope.out 
  62. endif 
  63. set csverb 
  64. endif 
  65.  
  66. </span> 

因为我的文档中的原配置文件已经有了语法高亮:

” Vim5 and later versions support syntax highlighting. Uncommenting the next

” line enables syntax highlighting by default.

if has(“syntax”)

  syntax on

endif

所以我就没写了,您如果vimrc文件里面没有此项建议自己加上syntax on设置语法高亮

 

PS:在配置文件中符号后的内容是注释,而且在配置文件中是不需要添加符号的 ,这里关于cscopectagsTaglist的设置可以先写上,后面将对这三个插件有介绍。好了,现在去开一个Vim,编辑一个程序看看,是不是感觉很不一般呢?

好了,下面顺便演示下,智能补全的用法,我分四种情况:1、前面申明过的变量或者函数名的补全;2、结构体等自建结构的补全;3STL等标准库的补全;4、括号、引号等自动匹配补全。

对于第一种情况,写程序的过程中,直接用CTRL+p即可选择,对于第二种情况,如果想申明了结构体T,想在输入T.时弹出成员供选择,只需在用之前按一下:CTRL+F12,然后效果如图:

clip_image002[6]

TagList插件,是一款基于ctags,vim代码窗口旁以分割窗口形式(如上图所示)显示当前的代码结构概览,增加代码浏览的便利程度的vim插件.

Vim中加载代码文件后,可以使用以下命令控制taglist

TlistOpen(直接Tlist也可)打开并将输入焦点至于标签列表窗口,效果如上图所示

TlistClose关闭标签列表窗口

TlistToggle切换标签列表窗口状态(打开←→关闭),标签列表窗口是否获得焦点取决于其他配置

ctl-wwctl-w+ 方向键窗口切换(taglist本质上是一个vim分隔窗口,因此可以使用ctl-w系列快捷键对窗口进行切换操作)Taglist窗口主要有以下操作

F1:打开帮助回车键:跳到光标所在的标记的定义处(如将光标移到main函数,按回车键)

o:新建一个窗口,跳到标记定义处

p:预览标记定义(仍然在taglist窗口)

空格:显示标记的原型(如函数原型)

u:更新标记列表(比如源文件新增了一个函数,并在保存后,可在taglist窗口按u)

s:选择排序字段(暂时我也不知道什么意思)

d:删除光标所在的taglist文件(如用vi打开了两个文件f1.c,f2.c可以删除f1.c的标记)

x:n放大/缩小taglist窗口

+:展开(指标记)

-:折叠

*:全部展开

=:全部折叠

[[:将光标移到前一个文件的起点

]]:将光标移到后一个文件的起点

q:退出taglist窗口

F1:关闭帮助

 

ctags使用简介VIM简单易用,大家只要看看VIM自带的vitutor,大约只要20分钟就能掌握VIM的用法,上面也简单介绍了点vim的用法。但是对于Linux下的C/C++的程序员,使用VIM+Ctags的组合来写程序也许是最佳的选择。^_^

尽管ctags也可以支持其它编辑器,但是它正式支持的只有VIM。并且VIM中已经默认安装了Ctags,它可以帮助程序员很容易地浏览源代码。熟练的使用ctags仅需记住下面七条命令:(很简单吧,呵呵)

1$ctags –R * ($Linux系统Shell提示符)

2.$ vi –t tag (请把tag替换为您欲查找的变量或函数名)

3:ts(ts助记字:tagslist, “:”开头的命令为VI中命令行模式命令)

4:tp(tp助记字:tagspreview)—此命令不常用,可以不用记

5:tn(tn助记字:tagsnext) —此命令不常用,可以不用记

6Ctrl+ ]跳到光标所在函数或者结构体的定义处

7Ctrl+ T返回查找或跳转

下面我们逐条的解释上面的命令:$ctags –R*”-R”表示递归创建,也就包括源代码根目录(当前目录)下的所有子目录。*”表示所有文件。这条命令会在当前目录下产生一个tags”文件,当用户在当前目录中运行vi时,会自动载入此tags文件。Tags文件中包括这些对象的列表:用#define定义的宏枚举型变量的值函数的定义、原型和声明名字空间(namespace)类型定义(typedefs)变量(包括定义和声明)类(class)、结构(struct)、枚举类型(enum)和联合(union)类、结构和联合中成员变量或函数VIM用这个tags”文件来定位上面这些做了标记的对象。剩下的命令就是定位这些对象的方法:$vi –t tag” :在运行vim的时候加上-t”参数,例如:[/usr/src]$vim -tmain这个命令将打开定义main”(变量或函数或其它)的文件,并把光标定位到这一行。如果这个变量或函数有多处定义,在VI命令行模式ts”命令就能列出一个列表供用户选择。tp”为上一个tag标记文件,tn”为下一个tag标记文件。

当然,若当前tags文件中用户所查找的变量或函数名只有一个,:tp,:tn”命令不可用。

(最方便的方法是把光标移到变量名或函数名上,然后按下Ctrl+]”,这样就能直接跳到这个变量或函数定义的源文件中,并把光标定位到这一行。用Ctrl+T”可以退回原来的地方。即使用户使用了NCtrl+]”查找了N个变量,按NCtrl+t”也能回到最初打开的文件,它会按原路返回 。 ^_^

注意:运行vim的时候,必须在tags”文件所在的目录下运行。否则,运行vim的时候还要用:settags=”命令设定tags”文件的路径,这样vim才能找到tags”文件。在完成编码时,可以手工删掉tags文件(帚把不到,灰尘不会自己跑掉^_^)。

有时候系统提示找不到tag”时不要一味着急,有可能你想要查询的函数时系统函数,如果这样,那妳幸运勒,可以使用Shift+K来查询。如果不是没也可以自己找到tags文件,打开查询,如果还是找不到哼哼,我也没辙了!

 

Cscope是一个类似ctags的工具。 你可以把它想作是超过频的ctags,因为它功能比ctags强大很多。

 Vim里,通过cscope查询结果来跳转就象跳转到其他的标签完全一样;它被保存在标签栈里。这样你就可以象使用tags一样在函数等等之间便捷的跳转。在VIM中使用cscope非常简单:

首先在目录下使用“cscope -kqb”生成cscope.out文件;

使用时先在VIM的命令行下调用cscope add/../../cscope.out”(或cs add /../../cscope.out)命令添加一个cscope数据库,然后就可以调cscope find”(或 cs f 命令进行查找了。

VIM支持8cscope的查询功能,如下:

c:Find functions calling this function//查找调用本函数的函数

d:Find functions called by this function //查找本函数调用的函数

e:Find this egrep pattern//查找egrep模式,相当于egrep功能,但查找速度快多了

f:Find this file //查找并打开文件,类似vimfind功能

g:Find this definition//查找函数、宏、枚举等定义的位置,类似ctags的功能

i:Find files #including this file //查找包含本文件的文件

s:Find this C symbol //查找C语言符号,即查找函数名、宏、枚举值等出现的地方

t:Find assignments to //查找指定的字符串

例如,我们想在代码中查找调用work()函数的函数,我们可以输入::cs f c work”,回车后发现没有找到匹配的功能,可能并没有函数调用work()。我们再输入:cs f s work”,查找这个符号出现的位置,现在vim列出了这个符号出现的所有位置。我们还可以进行字符串查找,它会双引号或单引号括起来的内容中查找。还可以输入一个正则表达式,这类似于egrep程序的功能。

cscopevim命令行下还可以执行下列操作

help: Show this message(Usage: help)

kill: Kill a connection(Usage: kill #)

reset:Reinit all connections(Usage: reset)

show: Show connections (Usage: show)