分类 调试 下的文章

根据软件代码规模,应用软件的开发大致分为三 种模式。

程序员个人开发的小软件

用例图

这种模式和早期的软件开发模式类似。 小软件开发用例图如图所示。

 

 

软件调试的特点

发现问题(测试)、定位问题和提出解决问题方 案、修改程序代码、验证全部由程序员负责。

软件调试 可以分为静态调试与动态调试。

1、静态调试。 源程序代码编译时同时对源代码进行静态检查, 编译器提供了源代码各种编程错误和错误所在的位 置。 静态调试就是程序员逐条修改编译器提示的错 误,通过代码编译这一关。

2、动态调试。 动态调试分为查错和纠错。 查错就是对程序进行 功能性能测试,查找各种不符合设计要求的各种问题; 纠错就是根据发现的问题,查找原因,修改程序源代 码。 这里的软件调试工作包括软件测试。 动态调试通 常采用以下两种方式:

  • 仔细分析发现的问题,通过推理来查找发生 问题的原因。 程序员对程序的架构设计、编码实现十 分熟悉,往往能比较快地定位和处理问题。 这种方式 通常具有全局观念,可以避免解决问题过程中诱导出 现其他问题。
  • 通过调试工具采用人机交互方式调试代码。 这种方式是逐条执行和跟踪程序代码,观察各种状态 和变量的变化,检查是否符合程序设计的要求来定位 问题。 这种方式有助于查找程序代码的微观错误,要 求程序员对程序代码的实现十分熟悉。 这两种方式是互补的,综合应用调试程序代码。

3、版本管理。 版本管理通常采用小型软件配置管理工具VSS, 也可采用文件存储的方式

程序组软件开发

这种模式与软件开发中期的开发模式类似。 通常 软件分为多个软件模块,每个程序员仅负责自己开发 的软件模块。 这种开发模式通常用于中、小型软件的 开发。

角色和用例图

软件设计人员:负责软件设计,提供设计规格 文档。

程序开发组:程序代码编写和程序调试,负责软件 的版本管理和集成构建。

测试人员:负责软件功能、性能测试。 程序组开发的软件用例图如图所示

 

 

软件调试的特点

1、软件的设计工作和大部分测试工作从程序组 工作中分离出去。 设计人员负责软件设计,程序员负 责程序代码的实现,定位问题和提出解决问题方案往 往由设计人员和程序组共同合作处理,程序员负责软 件纠错(程序代码修改),测试人员负责测试工作。

2、调试分为两个阶段:

(1)、开发组自己测试软件。 程序员完成程序源代码的编写,程序代码的静态 检查,使用调试工具对程序代码进行功能点的调试。 所有的功能点都调试完成后,通过组内代码评审之后, 将源代码合入版本库。 开发组组长指定某个程序员负责程序代码的集成 构建,编译过程中发现的问题,反馈给相关的程序员进 行处理。 源代码完成集成构建之后,打包提交给测试 人员测试。

(2)、测试人员测试软件。 测试人员根据设计规格文档设计测试用例,测试 提交过来的软件包。 测试人员发现的各种问题反馈给 程序开发组进行软件调试处理。 程序开发组和设计人 员确定发生问题的原因,确定修改方案,分配给相关的 程序员进行代码纠错处理。 对于比较复杂的问题,软 件设计人员需要提供实现编码的设计文档。 程序代码修改后,进行验证和确认。

3、版本管理通常采用软件配置管理工具 SVN。 通过版本管理工具对程序员提交的代码进行冲突检 查,通过调试处理保证代码的兼容性和一致性。

项目组开发的软件

软件通常由多个模块组成,每个模块由若干开发 单元组成。 开发单元分配给程序员编写程序代码。 这 种开发模式通常用于大型软件的开发。

角色和用例图

1、软件设计组:提供总体和各模块的设计规格 文档。

2、软件开发组:按模块分为开发小组,开发小组 将开发单元分配给程序员进行程序编码。

3、软件配置管理员:负责基线和版本库的管理。

4、持续集成工程师:负责软件的持续集成工作,搭建的集成构建工程,通过制定定时任务来自动 完成从版本库更新代码、静态检查、编译、出包、冒烟测 试等任务。 冒烟测试也称为预测试,对集成构建成功 的软件包的主要功能进行快速自动化测试。 构建成 功,可以获得最新Build版本,建立新的编码基线。 持 续集成工程师进行全量构建生成内部转测试版本,提 交测试组进行的测试工作。

5、软件测试组:对软件转测试版本进行功能、性 能测试,通过后产生测试(Tested)基线。 为持续集成 工作提供进行冒烟测试的自动化测试用例脚本包,搭 建相应的测试环境。 项目组开发软件(通常为大型软件)用例图如图 所示。

 

软件调试的特点

1、软件设计人员和软件测试人员增加了,有的软 件项目测试人员比开发人员还要多。 软件测试不仅要 发现程序编码中的问题,而且测试软件设计中的问题。 设计中的问题自然由设计人员处理,程序编码中的问 题由设计人员和开发人员共同处理。

2、软件的版本管理和集成构建工作由专人负责,实行基线和版本库的管理。 基线管理[13-14]为全体开 发人员提供统一的开发基点,统一的程序接口。 通过 控制集成构建的频率,有助于及时发现程序代码问题。

3、软件调试分为三个阶段:

(1)、开发人员调试自己开发软件单元。 程序开发人员每天从版本库检出需要的文件,放 在本地作为工作副本开始工作。 在工作副本上进行查 看、修改、编译、运行、调试等操作。 为了提供高质量的 代码,需要对编写好的代码进行单元测试,静态走码检 查,冲突处理和本地构建工作,处理发现的各种问题。 最后将评审过的代码提交到版本库。 开发人员向版本 库提交时,要添加注释、说明、CR单号、修改原因等,以 保证可追溯。

(2)、处理持续集成工程师发现的问题。 通常持续集成工作包括静态测试、编译、链接和冒 烟测试,每一步发现问题都要反馈给相关开发人员处 理,直到通过集成构建。

(3)、处理测试组发现的问题。 测试组测试转测试版本,将测试结果反馈给相关 人员,对存在的问题逐一定位,查找原因,修改程序,对 每个软件缺陷问题进行跟踪管理,直到问题解决为止。

4、设计人员和程序员共同处理反馈的各种问题, 定位问题和提出解决问题方案。 程序员负责程序代码 修改,测试人员负责验证和确认工作。

5、版本管理可以选择SVN、ClearCase、Git等软件 配置管理工具。 通过版本管理工具进行软件的版本管 理、基线管理和代码冲突检查。

6、软件开发过程中采用持续集成和基线管理技 术,可以更有效地进行开发和调试工作。

在windbg中,可以使用Ctrl+Alt+D查看调试器的内部信息流。在KD中,使用Ctrl+D和ENTER来切换输出。启用这个输出,我可以看到调试器无法从调试端口读取数据,而且它正在超时。错误“SYNCTARGET:Timeout.”清楚地表明调试主机无法与调试目标通信,尤其是在“Send Break-in”消息之后出现此错误时。

 

因为我在Hyper-V虚拟机上使用命名管道,所以我知道我没有坏电缆,尽管这是导致内核调试失败的常见原因。我还知道虚拟机的配置是正确的,我可以将调试器用于这台服务器上的其他虚拟机。问题很可能是在虚拟机中运行的操作系统。
通过检查设备管理器,我能够确认在虚拟机中运行的操作系统的配置有问题。bcdedit设置被配置为使用COM1,这将使COM1在操作系统中不可用,但是,COM1出现在设备管理器中。由于某些原因,调试器在启动时没有像配置的那样捕获COM1。

 

检查此服务器的bcd配置时,我发现bcd配置不正确。在普通Windows 7或Windows Server 2008 R2操作系统的bcd存储中,bcdedit的Windows引导加载程序部分具有继承设置。您可以使用命令“bcdedit/enum all”从提升的命令提示符查看系统上的此信息。通常,Windows引导加载程序继承{bootloadersettings},{bootloadersettings}继承{globalsettings},{globalsettings}继承{dbgsettings}。如果没有继承设置,则引导加载程序将无法读取调试器配置。
下面是损坏的虚拟机的bcd设置。您可以看到所有正常继承的设置都丢失了。

C:\Windows\system32>bcdedit /enum all



Windows Boot Manager
--------------------identifier {bootmgr}

device partition
=C:

path \bootmgr

description Windows Boot Manager

locale en
-US

default {current}

displayorder {current}

timeout
30Windows Boot Loader-------------------identifier {current}

device partition
=C:

path \Windows\system32\winload.exe

description Windows Server
2008R2 Standard (recovered)

locale en
-US

osdevice partition
=C:

systemroot \Windows

resumeobject {2ec5363f
-2a92-11e1-bbe4-806e6f6e6963}

usefirmwarepcisettings No

debug Yes



Resume from Hibernate
---------------------identifier {2ec5363f-2a92-11e1-bbe4-806e6f6e6963}

device partition
=C:

path \Windows\system32\winresume.exe

description Windows Server
2008R2 Standard (recovered)

locale en
-US

inherit {resumeloadersettings}

filedevice partition
=C:

filepath \hiberfil.sys

debugoptionenabled Yes



Windows Memory Tester
---------------------identifier {memdiag}

device partition
=C:

path \boot\memtest.exe

description Windows Memory Diagnostic

locale en
-US



Debugger Settings
-----------------identifier {dbgsettings}

debugtype Serial

debugport
1baudrate115200

软件调试的概念

软件调试是泛指重现软件缺陷问题,定位和 查找问题根源,最终解决问题的过程。 软件调试通常有如下两种不同的定义:

  • 定义1:软件调试是为了发现并排除软件程序中 的错误,可以通过某种方法控制被调试程序的执行过 程,以便随时查看和修改被调试程序执行状态的方法。 在该定义中,软件测试属于软件调试的一部分,与 牛津词典中的调试定义类似。 在牛津词典中调试定义 为:“识别和排除计算机硬件或软件中错误的过程。”
  • 定义2:调试是执行一次成功的测试之后所要进 行的工作。 所谓成功的测试,是指它可以证明程序没 有实现预期的功能。 调试包含两个步骤,从执行了一个成功测试用例,发现问题后开始;第一步,确定程序 中可疑错误的准确性质和位置;第二步,修改错误。 在该定义中软件测试从调试工作中分离出来。

软件调试的内涵

软件调试是将编制的程序投入实际运行前,用手工或编译程序等方法进行测试,修正语法错误和逻辑错误的过程。这是保证计算机信息系统正确性的必不可少的步骤。编完计算机程序,必须送入计算机中测试。根据测试时所发现的错误,进一步诊断,找出原因和具体的位置进行修正。

调试这个术语可能意味着很多不同的事情,但最字面的意思是,它意味着从代码中删除错误、异常和bug。现在,有很多方法可以做到这一点。例如,可以通过扫描代码以查找输入错误或使用代码分析器进行调试。您可以使用性能分析器调试代码。或者,可以使用调试器进行调试。

软件调试的基本过程

按照定义1,软件系统调试的基本过程如下:

  1. 用编辑程序把编制的源程序按照一定的书写格式送到计算机中,编辑程序会根据使用人员的意图对源程序进行增、删或修改。
  2. 把送入的源程序翻译成机器语言,即用编译程序对源程序进行语法检查并将符合语法规则的源程序语句翻译成计算机能识别的“语言”。如果经编译程序检查,发现有语法错误,那就必须用编辑程序来修改源程序中的语法错误,然后再编译,直至没有语法错误为止。
  3. 使用计算机中的连接程序,把翻译好的计算机语言程序连接起来,并扶植成一个计算机能真正运行的程序。在连接过程中,一般不会出现连接错误,如果出现了连接错误,说明源程序中存在子程序的调用混乱或参数传递错误等问题。这时又要用编辑程序对源程序进行修改,再进行编译和连接,如此反复进行,直至没有连接错误为止。
  4. 将修改后的程序进行试算,这时可以假设几个模拟数据去试运行,并把输出结果与手工处理的正确结果相比较。如有差异,就表明计算机的程序存在有逻辑错误。如果程序不大,可以用人工方法去模拟计算机对源程序的这几个数据进行修改处理;如果程序比较大,人工模拟显然行不通,这时只能将计算机设置成单步执行的方式,一步步跟踪程序的运行。一旦找到问题所在,仍然要用编辑程序来修改源程序,接着仍要编译、连接和执行,直至无逻辑错误为止。也可以在完成后再进行编译。

按照定义2,软件系统调试的基本过程如下:

  1. 重现问题:重现软件测试发现的问题;
  2. 问题定位:确定可能发生问题的程序段位置;
  3. 查找原因:分析相关代码,确定导致缺陷问题 的内在原因;
  4. 设计方案:提出软件缺陷问题解决方案;
  5. 修改代码:根据设计方案修改程序代码;
  6. 验证和确认:采用审查、分析和测试等技术来 确定错误是否被排除,是否引入了新的错误。

上述6个步骤不断迭代进行,直至问题解决。 软件调试基本过程如图1所示:

 

在这些步骤中,问题定位和查找原因是软件调试 的关键环节,其工作量约占总工作量的90%以上。 软 件调试是一项既耗时又费力,同时又富有技巧性的工 作。 目前软件调试中的问题定位研究的比较多。

 

 

可以看到,定义一的流程更贴合我们的日常开发测试工作;而定义二的流程更贴合我们测试特别是软件发布或上线后发现问题的处理相关工作。

软件调试基本特征

  • 广泛的关联性
    需要调试人员有着雄厚的计算机基础知识(包括操作系统、开发语言、工具等)以及精通面向的业务问题域知识。
  • 难度大
    从"广泛的关联性"就可以知道难度大不大了。当然也看面临的具体问题和调试人员的素质
  • 难以预估完成时间
    这个时间真的是没法预估,除非某个问题的领域专家和对软件整体架构及代码的理解熟悉程度。

软件调试分类

  • 按调试目标的系统环境分类:Windows下的软件调试、Linux下的软件调试、Dos下的软件调试等
  • 按目标代码的执行方式分:
    脚本程序 – 脚本调试器
    执行编译的程序:
            先编译为中间代码,在运行时再动态编译为当前CPU能够执行的目标代码(比如C#开发的.NET程序) – 托管调试
            直接编译和链接成目标代码的程序(C/C++) – 本地调试
            兼具以上两种的 – 混合调试
  • 按目标代码的执行模式分:用户态调试(User Mode Debugging)、内核态调试(Kernel Mode Debugging);
    在Windows这样的多任务操作系统中,作为保证安全和秩序的一个根本措施,系统定义了两种执行模式,即低特权等级的用户模式(User Mode)和高特权等级的内核模式(Kernel Mode)。
    应用程序代码是运行在用户模式下的,操作系统的内核、执行体和大多数设备驱动程序是运行在内核模式的。
  • 按软件所处的阶段分:开发期调试、产品期调试(分界线是产品的正式发布)
  • 按调试器和调试目标的相对位置分:本机提哦啊哈斯、远程调试
  • 按调试目标的活动性分:活动目标调试、转储文件调试   

符号服务器访问是对比调试器。能够自动下载与当前系统匹配的所有程序(或者最终用户系统,如果我们想调试崩溃转储)的符号是非常方便的。但是有一个小问题:有些模块的符号在公共符号服务器上没有。但是调试器并不知道,因此每次我们启动调试会话时,调试器都会连接符号服务器并尝试下载模块的符号,但没有成功。因此,调试会话的启动时间会显著增加,特别是对于使用大量第三方组件的应用程序,这些组件的符号无法定义在Microsoft symbol server上。
幸运的是,有一个解决方案-我们可以告诉调试器,一些模块应该从符号服务器搜索中排除。

以下是操作方法:

1、升级symsrv.dll.
这个小DLL负责符号服务器的访问。净我们应该将它升级到一个更新的版本,这个版本是随Windows调试工具提供的。在我们下载并安装调试工具之后,symsrv.dll应该从其安装目录复制到<VSInstallDir>\Common7\IDE目录。
2、在symsrv.ini文件中指定排除列表。

此文件应创建在<VSInstallDir>\Common7\IDE目录(其中symsrv.dll位置)。

此文件的[exclusions]部分应包含要从符号服务器搜索中排除的文件列表。支持通配符,我更喜欢用*通配符替换所有文件扩展名,以确保排除所有可能的调试信息文件格式。
这是一个样品symsrv.ini要求调试器排除msxml4.dll和shlwapi.dll从搜索服务器符号:

;start of symsrv.ini
[exclusions]
msxml4.*
shlwapi.*
;end of symsrv.ini

在 WinDbg 中,源窗口显示已加载到调试器中的源文件。

如何打开源代码窗口

  • 通过菜单File--->Open Source File打开源代码文件,窗口随之打开
  • 通过快捷键Ctrl+O
  • 通过工具栏
  • 设置源路径,调试器实时自动打开

使用源代码窗口

通过上面方式打开的窗口如下:

 

每个源窗口都显示一个源文件的文本。 不能在调试器中编辑源文件。每个源窗口都具有包含附加命令的快捷菜单。 若要访问菜单,请右键单击标题栏,或单击窗口右上角附近显示的图标(显示源窗口工具栏快捷菜单的按钮屏幕截图)。 以下列表描述了一些菜单命令:

 

  • Set instruction pointer to current line 会将指令指针的值更改为对应于当前行的指令。 此命令等效于使用 "编辑 |设置当前指令命令或按 CTRL + SHIFT + I.

  • Edit this file 在文本编辑器中打开源文件。编辑器由WinDiff编辑器注册表信息或WINDBG_INVOKE_editor环境变量的值确定。例如,当WINDBG_INVOKE_EDITOR的值为以下值时。

     
    c:\my\path\myeditor.exe -file %f -line %l