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

debugging in a multiple-activities context

多活动上下文中的调试

       套接字socket是一种类似于文件描述符的抽象,正如人们使用文件描述符在文件系统对象上执行IO操作一样,通过套接字向网络连接读写信息。

       进程和线程之间的主要区别是:与进程一样,虽然每个线程有自己的局部变量,但是多线程环境中父程序的全局变量被所有线程共享,并作为在线程之间通信的主要方法。

       并行编程架构主要有两种:共享内存和消息传递

l  共享内存:多个CPU都具有对某些共同的物理内存的访问权限,在一个CPU上运行的代码与在其他CPU上运行的代码通信,方法是通过在这个共享内存上读写,这与多线程应用程序中的线程通过共享地址空间与另一个线程通信基本一样;

l  消息传递:在各个CPU上运行的代码只能访问该CPU的本地内存,它通过通信媒介发送成为消息的字符串来与其他CPU上的代码通信,通常这是某种网络,通过某种通信协议()或者适用于消息传递引用程序的专门软件基础结构。