Delphi应用程序的调试(一)集成式调试器是DelphiIDE的一个重要特性。该调试器使用户能方便地设置断点、监视变量、检查对象等等。在运行程序时,使用该调试器能快速查找出程序发生了什么(或未发生什么)。一个号的调试器对程序开发的效率至关重要。调试工作容易被忽略。我也是刚开始学习Windows编程时,很长时间都未理睬调试器,因为当时忙于学习如何编写Windows应用程序。当后来知道这是一个很有价值的调试器的后,才后悔为什么没有早点使用它。希望大家从我的经历中吸取教训。一、为什么使用调试器对于这个问题的回答很简单:调试器能帮助用户查找程序中的错误。但是,调试过程不仅仅是查找错误,它还是一个开发工具。尽管调试很重要,但仍有很多程序员不愿花时间来学习如何使用IDE调试器的各种性能。结果,他们付出了更多的时间和精力,更不用提由于查不出程序中的错误而导致的失败。可在调试器下启动程序,开始调试,也可按【F9】自动地使用调试器。二、调试器菜单项在详细介绍调试器之前,先来看看有关调试器的菜单项目。其中一些菜单项在主菜单的【Run】下,另一些在CodeEditor的快捷菜单上。1、CodeEditor快捷菜单中的调试菜单项【ToggleBreakpoint】快捷键【F5】在CodeEditor中的当前行上设置或关闭一个断点【RuntoCursor】快捷键【F4】启动程序并运行该程序至CodeEditor中光标所在行【GotoAddress…】快捷键【Ctrl+Alt+G】允许用户指定程序中的一个地址,程序在此地址恢复执行【Inspect…】快捷键【Alt+F5】为光标所在对象打开DebugInspect窗口【Evaluate/Modify…】快捷键【Ctrl+F7】允许用户在运行时查看、修改变量【AddWatchatCursor】快捷键【Ctrl+F5】将光标所指变量添加到WatchList中【ViewCPU】快捷键【Ctrl+Alt+C】显示CPU窗口主菜单上【Run】菜单项是一个下拉菜单,有若干菜单项与调试器下运行程序有关。Run菜单项使用户能在调试器下启动一个程序、终止运行在调试器下的程序、命名若干个函数。其中有些菜单项与CodeEditor中的菜单项目一样。2、主菜单【Run】下的菜单项目Run——【F9】编译程序并在IDE调试器控制下运行该程序。Parameters——【无】允许用户为程序输入命令行参数并在调试DLL时指定一个宿主应用程序(hostapplication)。StepOver——【F8】执行执行点所在的源代码行,并停在下一个源代码行。TraceInto——【F7】跟踪执行点处的方法。TracetoNextSourceLine——【Shift+F7】移动执行点到程序源代码的下一行。RuntoCursor——【F4】运行程序,并且当程序执行到源代码当前行时暂停。ShowExecutionPoint——【无】在CodeEditor中显示程序执行点。如果需要可滚动源代码窗口,仅当程序暂停执行时可用。ProgramPause——【无】执行点一进入程序源代码就暂停程序执行。ProgramReset——【Ctrl+F2】无条件终止程序并返回DelphiIDE。Inspect…——【无】显示Inspect对话框,因而用户可输入要检查对象的对象名。Evaluate/Modify…——【Ctrl+F7】显示“Evaluate/Modify”对话框。AddWatch…——【Ctrl+F5】显示“WatchProperties”对话框。AddBreakpoint——【无】显示一个子菜单,该子菜单包含有增加源代码、地址、数据或模块装入断点的菜单项。如下图:以上这些菜单项在调试应用程序时经常要使用,这些调试操作的键盘快捷键也应该熟悉。Delphi应用程序的调试(二)使用断点使用断点(UsingBreakpoints)当用户从DelphiIDE运行程序时,程序全速运行,只会在设置了断点的地方停住。NewTerm断点(breakpoint)是一种标记,用以通知编译器,当程序运行到断点所在位置时暂停程序的执行。设置和清除断点(SettingandClearingBreakpoints)断点的设置可通过点击CodeEditor的沟槽来进行;要在代码的某一行暂停程序执行,就在沟槽中与该行相对应的位置上点击鼠标,该行就被设置上一个断点;此时,沟槽中出现一个断点图标(一个红色圆圈),并且断点所在行以红色加亮显示,如下图:点击沟槽中的断点图标,与之对应的断点就会被删除。也可以按【F5】键或从CodeEditor的快捷菜单中选择【ToggleBreakpoint】菜单项来触发或取消断点。Note只允许在能生成实际代码的行上设置断点。在空白行、注释或声明行上设置的断点时无效断点,当用户在这一类的行上设置断点,调试器会提出警告。试图在下列行上设置断点,都会产生一个无效断点警告:可在函数或过程的end语句行上设置断点。如果在无效行上设置断点,CodeEditor会以绿色显示断点,如上图所示。在调试器下运行的程序,在不碰到断点时,与通常的程序运行完全一样;当碰到断点时,IDE会被提到最顶层,并且源代码中的断点所在行被加亮显示。如果使用的是缺省颜色格式,则程序停止处的行以红色加亮显示,如下图,红色断点旁有一个绿色小箭头:NewTerm执行点(executionpoint)是指源代码中下一步要执行的代码行。当用户一步一步调试程序时,执行点以蓝色加亮显示,并且在CodeEditor沟槽中显示一个绿色箭头符号。提醒:以蓝色加亮显示的行还未被执行;当恢复程序执行时才执行它。如下图:Note当执行点所在行以蓝色加亮显示,除非该行包含一个断点(此时,该行以红色加亮显示)。沟槽中的绿色箭头是当前执行点的最精确指示,因为它不受加亮显示颜色的影响。当程序在断点处暂停执行时,用户可查看变量、查看调用栈、浏览符号或在代码中步进。检查完变量和对象后,可点击Run按钮恢复程序的执行,这时应用程序就会再次正常运行,直至碰到下一个断点。Note当程序在断点处暂停执行后,用户一般都要检测代码编写错误。如果用户在调试会话中间修改了源代码,然后按Run按钮恢复程序执行,IDE就会显示一个消息框提示用户是否要重建源代码;如果用户选Yes,当前过程就会被终止,源代码被重新编译,并重新启动该程序。这样操作就有一个问题,程序无法正常关闭,当前正使用的资源未被释放。这样极可能导致内存泄露(memoryleaks)。建议大家正常终止程序,然后再重新编译应用程序。断点列表窗口(TheBreakpointListWindow)DelphiIDE记载用户设置的断点,可通过BreakpointList(断点列表)窗口查看这些断点。从主菜单上选择【View|DebugWindows|Breakpoint】菜单项来查看断点列表,如下图:NotePass栏不是显示某个断点被碰上的次数,它只是显示用户为断点设置的通过条件。1、快捷菜单(BreakpointListContextMenus)Enabled——允许使用或禁止使用某个断点。如果一个断点被禁止使用,它在BreakpointList窗口中的符号就会变灰;它在源窗口中的断点符号也会变灰;并且该断点所在行以绿色加亮显示,表示该断点被禁用。如下图:Delete——删除断点。ViewSource——滚动CodeEditor中的源文件来显示包含断点的源代码行。EditSource——将编辑光标放置到源代码中包含断点的行上。并将输入焦点切换到CodeEditor上。Properties——显示“SourceBreakpointProperties”断点属性对话框。Breakpoints——显示断点有关的子菜单,如下图:Dockable——确定“BreakpointList”窗口是否可泊位。Note快捷菜单中的【Add】菜单项作用不大,因为,在CodeEditor中设置断点要比通过BreakpointList窗口中的Add命令来添加断点容易的多。2、断点的启用和禁用(EnablingandDisablingBreakpoints)用户在任何时候都可以禁止和启用断点。如果用户想要正常运行程序,就可将程序中的断点暂时禁用;以后需要时可启用该断点而不必重新创建它。调试器忽略被禁用的断点。要启用或禁用一个断点。在“BreakpointList”窗口中用鼠标右键点击该断点,并从快捷菜单中选择【Enabled】项。3、修改断点(ModifyingBreakpoints)要修改断点,可从“BreakpointList”窗口中选择【Properties】菜单项,此时会显示“SourceBreakpointProperties”对话框,如下图:修改断点的主要原因是增加断点条件,在之后的讲解中将要重点介绍。要删除一个断点,可在“BreakpointList”中选择该断点,并按键盘上的【Delete】键盘。要删除所有断点,可单击鼠标右键,然后选择【DeleteAll】。下面将要讲解断点的两种类型:简单断点和条件断点。简单断点(SimpleBreakpoints)简单断点是指这样一种断点,程序一执行到断点处就会被挂起。按缺省方式设置的断点就是简单断点。简单断点不需要多作解释。一碰到简单断点,程序执行就会暂停,此时调试器等待用户的输入。大多数时候都是使用简单断点;当用户需要更多地控制调试过程时,才使用条件断点。条件断点(ConditionalBreakpoints)若碰到的断点是条件断点,则仅当预定义的条件满足时,才会暂停程序执行。要创建一个条件断点,可先在CodeEditor中设置该断点;然后从主菜单选择【View|DebugWindows|Breakpoint】菜单项调出“BreakpointList”窗口,用鼠标右键点击要设置的断点并选择【Properties】菜单项,显示出“SourceBreakpointProperties”对话框,在此对话框中设置断点的条件。条件断点有两种类型:第一种类型是条件表达式断点。在“SourcebreakpointProperties”对话框中的“Condition”字段中输入条件表达式。如下图:当程序运行时,碰到条件表达式断点就会先求条件表达式的值,若条件表达式的值为True,则暂停程序执行;若条件表达式的值为False时,则该断点被忽略。例如:设置的条件表达式为:X20;当程序运行到该断点时,若X大于20则暂停程序的执行;若X不大于20,则程序继续往下执行。第二种类型是通过计数(passcount)断点。对于一个通过计数断点,只要当碰上该断点的次数达到指定次数时,程序才会在该断点处暂停执行。要指定一个通过计数断点,可在“SourceBreakpointProperties”对话框中编辑该断点并为PassCount字段指定一个值。若将一个断点的通过计数设置成3,则程序会在第三次碰到该断点时暂停程序执行。Note通过计数是从1开始,不是从0开始。就像前面所指出的,通过计数为3,意味着当程序第三次碰上某个断点时,该断点才有效。当程序需要在程序执行通过某个断点若干次后再暂停程序执行来检查变量、步进调试代码或执行其他调试任务时,可使用通过计数断点。Note条件断点会放慢程序的执行速度,因为每当碰上条件断点时,都要对条件求值。在调试期间,如果程序运行缓慢,可检查一下断点列表,看是否存在不必要的条件断点。Note用户可灵活运用条件断点来减慢程序执行速度。如果用户希望某段程序低速运行以便查看,可在该代码段中设置一个或多个条件断点。将断点的条件设置成永远不能成立的条件,则程序执行会放慢速度,但不会停住。运行至光标处命令(TheRuntoCursorCommand)还有一个调试命令值得一提,就是“RuntoCursor”命令,可从主菜单【Run|RuntoCursor】选择此命令。当用“RuntoCursor”命令运行程序时,程序会在包含编辑光标的源代码行上停止运行,就好像该