Delphi应用程序的调试(1-10)

http://www.cnblogs.com/pchmonster/archive/2012/05/08/2489754.html

Delphi应用程序的调试(一)

集成式调试器是Delphi IDE的一个重要特性。该调试器使用户能方便地设置断点、监视变量、检查对象等等。在运行程序时,使用该调试器能快速查找出程序发生了什么(或未发生什么)。一个号的调试器对程序开发的效率至关重要。

调试工作容易被忽略。我也是刚开始学习Windows编程时,很长时间都未理睬调试器,因为当时忙于学习如何编写Windows应用程序。当后来知道这是一个很有价值的调试器的后,才后悔为什么没有早点使用它。希望大家从我的经历中吸取教训。

一、为什么使用调试器

对于这个问题的回答很简单:调试器能帮助用户查找程序中的错误。

但是,调试过程不仅仅是查找错误,它还是一个开发工具。尽管调试很重要,但仍有很多程序员不愿花时间来学习如何使用IDE调试器的各种性能。结果,他们付出了更多的时间和精力,更不用提由于查不出程序中的错误而导致的失败。

可在调试器下启动程序,开始调试,也可按【F9】自动地使用调试器。

二、调试器菜单项

在详细介绍调试器之前,先来看看有关调试器的菜单项目。其中一些菜单项在主菜单的【Run】下,另一些在Code Editor的快捷菜单上。

1、Code Editor快捷菜单中的调试菜单项

image

  • 【Toggle Breakpoint】快捷键【F5】在Code Editor中的当前行上设置或关闭一个断点
  • 【Run to Cursor】快捷键【F4】启动程序并运行该程序至Code Editor中光标所在行
  • 【Goto Address…】快捷键【Ctrl + Alt + G】允许用户指定程序中的一个地址,程序在此地址恢复执行
  • 【Inspect…】快捷键【Alt + F5】为光标所在对象打开Debug Inspect窗口
  • 【Evaluate/Modify…】快捷键【Ctrl + F7】允许用户在运行时查看、修改变量
  • 【Add Watch at Cursor】快捷键【Ctrl + F5】将光标所指变量添加到Watch List中
  • 【View CPU】快捷键【Ctrl + Alt + C】显示CPU窗口

主菜单上【Run】菜单项是一个下拉菜单,有若干菜单项与调试器下运行程序有关。Run菜单项使用户能在调试器下启动一个程序、终止运行在调试器下的程序、命名若干个函数。其中有些菜单项与Code Editor中的菜单项目一样。

2、主菜单【Run】下的菜单项目

image

  • Run——【F9】编译程序并在IDE调试器控制下运行该程序。
  • Parameters——【无】允许用户为程序输入命令行参数并在调试DLL时指定一个宿主应用程序(host application)。
  • Step Over——【F8】执行执行点所在的源代码行,并停在下一个源代码行。
  • Trace Into——【F7】跟踪执行点处的方法。
  • Trace to Next Source Line——【Shift + F7】移动执行点到程序源代码的下一行。
  • Run to Cursor——【F4】运行程序,并且当程序执行到源代码当前行时暂停。
  • Show Execution Point——【无】在Code Editor中显示程序执行点。如果需要可滚动源代码窗口,仅当程序暂停执行时可用。
  • Program Pause——【无】执行点一进入程序源代码就暂停程序执行。
  • Program Reset——【Ctrl + F2】无条件终止程序并返回Delphi IDE。
  • Inspect…——【无】显示Inspect对话框,因而用户可输入要检查对象的对象名。
  • Evaluate/Modify…——【Ctrl + F7】显示“Evaluate/Modify”对话框。
  • Add Watch…——【Ctrl + F5】显示“Watch Properties”对话框。
  • Add Breakpoint——【无】显示一个子菜单,该子菜单包含有增加源代码、地址、数据或模块装入断点的菜单项。如下图:image

以上这些菜单项在调试应用程序时经常要使用,这些调试操作的键盘快捷键也应该熟悉。


Delphi应用程序的调试(二)使用断点

使用断点(Using Breakpoints)

当用户从Delphi IDE 运行程序时,程序全速运行,只会在设置了断点的地方停住。

New Term

断点(breakpoint)是一种标记,用以通知编译器,当程序运行到断点所在位置时暂停程序的执行。

设置和清除断点(Setting and Clearing Breakpoints)

断点的设置可通过点击Code Editor的沟槽来进行;要在代码的某一行暂停程序执行,就在沟槽中与该行相对应的位置上点击鼠标,该行就被设置上一个断点;此时,沟槽中出现一个断点图标(一个红色圆圈),并且断点所在行以红色加亮显示,如下图:

image

点击沟槽中的断点图标,与之对应的断点就会被删除。也可以按【F5】键或从Code Editor的快捷菜单中选择【Toggle Breakpoint】菜单项来触发或取消断点。

Note

只允许在能生成实际代码的行上设置断点。在空白行、注释或声明行上设置的断点时无效断点,当用户在这一类的行上设置断点,调试器会提出警告。试图在下列行上设置断点,都会产生一个无效断点警告:

0271

可在函数或过程的end语句行上设置断点。

如果在无效行上设置断点,Code Editor会以绿色显示断点,如上图所示。

在调试器下运行的程序,在不碰到断点时,与通常的程序运行完全一样;当碰到断点时,IDE会被提到最顶层,并且源代码中的断点所在行被加亮显示。如果使用的是缺省颜色格式,则程序停止处的行以红色加亮显示,如下图,红色断点旁有一个绿色小箭头:

image

New Term

执行点(execution point)是指源代码中下一步要执行的代码行。

当用户一步一步调试程序时,执行点以蓝色加亮显示,并且在Code Editor沟槽中显示一个绿色箭头符号。提醒:以蓝色加亮显示的行还未被执行;当恢复程序执行时才执行它。如下图:

image

Note

当执行点所在行以蓝色加亮显示,除非该行包含一个断点(此时,该行以红色加亮显示)。沟槽中的绿色箭头是当前执行点的最精确指示,因为它不受加亮显示颜色的影响。

当程序在断点处暂停执行时,用户可查看变量、查看调用栈、浏览符号或在代码中步进。检查完变量和对象后,可点击Run按钮恢复程序的执行,这时应用程序就会再次正常运行,直至碰到下一个断点。

Note

当程序在断点处暂停执行后,用户一般都要检测代码编写错误。如果用户在调试会话中间修改了源代码,然后按Run按钮恢复程序执行,IDE就会显示一个消息框提示用户是否要重建源代码;如果用户选Yes,当前过程就会被终止,源代码被重新编译,并重新启动该程序。

这样操作就有一个问题,程序无法正常关闭,当前正使用的资源未被释放。这样极可能导致内存泄露(memory leaks)。建议大家正常终止程序,然后再重新编译应用程序。

断点列表窗口(The Breakpoint List Window)

Delphi IDE记载用户设置的断点,可通过Breakpoint List(断点列表)窗口查看这些断点。从主菜单上选择【View | Debug Windows | Breakpoint】菜单项来查看断点列表,如下图:

image

Note

Pass栏不是显示某个断点被碰上的次数,它只是显示用户为断点设置的通过条件。

1、快捷菜单(Breakpoint List Context Menus)

image

  • Enabled——允许使用或禁止使用某个断点。如果一个断点被禁止使用,它在Breakpoint List窗口中的符号就会变灰;它在源窗口中的断点符号也会变灰;并且该断点所在行以绿色加亮显示,表示该断点被禁用。如下图: 
    image
  • Delete——删除断点。
  • View Source——滚动Code Editor中的源文件来显示包含断点的源代码行。
  • Edit Source—— 将编辑光标放置到源代码中包含断点的行上。并将输入焦点切换到Code Editor上。
  • Properties—— 显示“Source Breakpoint Properties”断点属性对话框。
  • Breakpoints—— 显示断点有关的子菜单,如下图: 
    image
  • Dockable—— 确定“Breakpoint List”窗口是否可泊位。

Note

快捷菜单中的【Add】菜单项作用不大,因为,在Code Editor中设置断点要比通过Breakpoint List窗口中的Add命令来添加断点容易的多。

2、断点的启用和禁用(Enabling and Disabling Breakpoints)

用户在任何时候都可以禁止和启用断点。如果用户想要正常运行程序,就可将程序中的断点暂时禁用;以后需要时可启用该断点而不必重新创建它。调试器忽略被禁用的断点。

要启用或禁用一个断点。在“Breakpoint List”窗口中用鼠标右键点击该断点,并从快捷菜单中选择【Enabled】项。

3、修改断点(Modifying Breakpoints)

要修改断点,可从“Breakpoint List”窗口中选择【Properties】菜单项,此时会显示“Source Breakpoint Properties”对话框,如下图:

image

修改断点的主要原因是增加断点条件,在之后的讲解中将要重点介绍。

要删除一个断点,可在“Breakpoint List”中选择该断点,并按键盘上的【Delete】键盘。要删除所有断点,可单击鼠标右键,然后选择【Delete All】。

image

下面将要讲解断点的两种类型:简单断点和条件断点。

简单断点(Simple Breakpoints)

简单断点是指这样一种断点,程序一执行到断点处就会被挂起。按缺省方式设置的断点就是简单断点。简单断点不需要多作解释。一碰到简单断点,程序执行就会暂停,此时调试器等待用户的输入。大多数时候都是使用简单断点;当用户需要更多地控制调试过程时,才使用条件断点。

条件断点(Conditional Breakpoints)

若碰到的断点是条件断点,则仅当预定义的条件满足时,才会暂停程序执行。

要创建一个条件断点,可先在Code Editor中设置该断点;然后从主菜单选择【View | Debug Windows | Breakpoint】菜单项调出“Breakpoint List”窗口,用鼠标右键点击要设置的断点并选择【Properties】菜单项,显示出“Source Breakpoint Properties”对话框,在此对话框中设置断点的条件。

条件断点有两种类型:

  • 第一种类型是条件表达式断点。 
    在“Source breakpoint Properties”对话框中的“Condition”字段中输入条件表达式。如下图: 
    image 
    当程序运行时,碰到条件表达式断点就会先求条件表达式的值,若条件表达式的值为True,则暂停程序执行;若条件表达式的值为False时,则该断点被忽略。 
    例如:设置的条件表达式为:X > 20;当程序运行到该断点时,若X大于20则暂停程序的执行;若X不大于20,则程序继续往下执行。
  • 第二种类型是通过计数(pass count)断点。 
    对于一个通过计数断点,只要当碰上该断点的次数达到指定次数时,程序才会在该断点处暂停执行。要指定一个通过计数断点,可在“Source Breakpoint Properties”对话框中编辑该断点并为Pass Count字段指定一个值。若将一个断点的通过计数设置成3,则程序会在第三次碰到该断点时暂停程序执行。 

    Note

    通过计数是从1开始,不是从0开始。就像前面所指出的,通过计数为3,意味着当程序第三次碰上某个断点时,该断点才有效。 
    当程序需要在程序执行通过某个断点若干次后再暂停程序执行来检查变量、步进调试代码或执行其他调试任务时,可使用通过计数断点。 

    Note

    条件断点会放慢程序的执行速度,因为每当碰上条件断点时,都要对条件求值。在调试期间,如果程序运行缓慢,可检查一下断点列表,看是否存在不必要的条件断点。 

    Note

    用户可灵活运用条件断点来减慢程序执行速度。如果用户希望某段程序低速运行以便查看,可在该代码段中设置一个或多个条件断点。将断点的条件设置成永远不能成立的条件,则程序执行会放慢速度,但不会停住。

运行至光标处命令(The Run to Cursor Command)

还有一个调试命令值得一提,就是“Run to Cursor”命令,可从主菜单【Run | Run to Cursor】选择此命令。当用“Run to Cursor”命令运行程序时,程序会在包含编辑光标的源代码行上停止运行,就好像该代码行上设置有断点一样。如下图:

image

Run to Cursor”可用作临时断点。当用户要马上检查某行源代码时,不必在该行上设置断点;只需将光标移到这一行上,然后选“Run to Cursor”(或按F4键),调试器会在程序运行至该行时暂停程序执行。就好像该行上设置了断点一样。使用“Run to Cursor”的好处是:当完成一段代码的调试后,不必清除断点。

以上测试均在Delphi7下通过。


Delphi应用程序的调试(三)监视变量

监视变量(Watching Variables)

当程序停在一个断点处时,用户做些什么呢?通常用户在断点处停下来是要检查变量的值,某个变量的值是否与预料的取值相同?或者某个变量取什么值(事先并不知道这个变量的取值)。

Watch List窗口的作用是使用户能检查变量的值。编程人员常常忽视这个简单而又根本的特性,因为他们没有花时间来完整地学习调试器的使用。用户可添加任意多的变量到Watch List中。下图就是调试会话期间的Watch List窗口。

image

变量名和变量值都显示在Watch List中。

Tooltip表达式求值(Tooltip Expression Evaluation)

调试器和Code Editor有一个很好的特性,它使检查变量值的工作变得更容易。这个特性就是Tooltip表达式求值器(expression evaluator),其缺省状态是打开,因此用户不需要做任何事情就能使用它。如果需要,也可以通过Editor Properties对话框的Code Insight页面来关闭它,如下图:

image

那么,什么是Tooltip表达式求值呢?它是这样工作的:当程序停在一个断点处,用户把编辑光标移到一个变量上,就会弹出一个提示窗口,其中显示该变量的当前值。这样就使快速检查变量的工作变得更容易,只需将光标移到变量上并稍等片刻。

Tooltip evaluator求值器对于不同的变量类型由不同的显示。对于常规数据成员(Integer、Char、Byte、String等等),显示变量的实际值;对于动态创建的对象(例如一个类的实例),Tooltip evaluator显示记录的全部元素。如下图所示:

image

image

Note

有时候Tooltip evaluator好像工作不正常。例如,若将编辑光标移到一个作用域外的变量上时,就不会显示提示窗口,因为Tooltip evaluator 无任何信息可显示。被编辑器优化过的变量也可能不能显示正确值。

当光标位于with块中时,Tooltip evaluator也不工作。例如,看下面这段代码:

1
2
3
4
5
6
7
8
9
10
11
var
   pp: Point;
begin
   with  pp do
   begin
     x := 20;
     y := 40;
   end;
 
   Caption := IntToStr(pp.x);
end;

如果把光标放到变量x上,Tooltip evaluator不会显示x的值,因为x属于with语句(Point变量)。如果将光标移到变量Point上,调试器会显示Point的值(包括x字段)。如下图:

image

Tooltip 表达式求值器很有用的,别忘记使用它。

Watch List快捷菜单(The Watch List Context Menu)

正如前面讲到的每一个Delphi窗口一样,Watch List也有它自己的快捷菜单。如下描述:

image

Edit Watch——打开Watch Properties对话框修改监视项属性 
Add Watch——打开Watch Properties对话框新监视项 
Enable Watch——启用一个已经禁用的监视项 
Disable Watch——禁用一个已启用的监视项 
Delete Watch——删除一个监视项 
Enable All Watches——启用所有已经禁用的监视项 
Disable All Watches——禁用所有已经启用的监视项 
Delete All Watches——删除所有监视项 
Add Group——增加一个监视组 
Delete Group——删除一个监视组 
Move Watch to Group——移动监视项到组 
Stay On Top——使Watch List窗口始终在最上层

Inspect——显示选中的监视项的有关信息 
Break When Changed——当监视窗口中的变量改变时,调试器将终端。监视变量以红色显示,表示Break When Changed起作用。 
Dockable——窗口是可泊位。

使用Watch Properties对话框(Using the Watch Properties Dialog Box)

 image

当用户增加或编辑监视项时,要使用Watch Properties对话框。如上图显示的是正在编辑pp变量的Watch Properties对话框。

位于对话框顶部的【Expression字段】,是用户输入要编辑或增加到Watch List中的变量名的地方,这个字段是一个组合框,可以用来选取以前用过的监视项。

但用户要检查数组时,使用【Repeat count字段】,比如,有一个20个整数元素的数组,要检查数组的头10个整数,可在【Expression字段】中输入数组的第一个元素(例如Array[0]),再在【Repeat count字段】中输入10。数组的头10个元素就会显示在Watch List中。如下图pp为有20个元素的整型数组:

image

Note

如果将数组名增加到Watch List中,则数组的全部元素都会显示在Watch List中。当要查看数组的部分元素时,使用【Repeat count字段】。

仅当检查浮点数时,采使用【Digits字段】;在此输入显示浮点数时要显示的有效位数,有效位后面的余数作四舍五入处理。【Enabled字段】确定监视项是否当前启用。

Watch Properties对话框上的其余选项都是显示选项。每一种数据类型都有一种缺省显示类型,当用户选中【Default】时,就使用缺省显示类型,Default查看选项的默认状态时“选中”的。选择其他的查看选项,就以其他方式查看数据。如下图:

image

要修改一个监视项,可在Watch List中点击该项,然后在右键快捷菜单中选择【Edit Watch…】菜单项,也可双击该监视项,快速打开Watch Properties对话框。

启用和禁用监视项(Enabling and Disabling Watch Items)

就像使用断点时一样,Watch List中每项都可被启用或禁用。当一个监视项被禁用时,它会变灰,并且它的值显示为<disabled>。如下图:

image

要禁用一个监视项,可点击Watch List中该项的名字,并从Watch List快捷菜单中选择【Disabled Watch】菜单项;要启用该监视项,就从快捷菜单中选【Enabled Watch】菜单项。

Note

用户可能希望禁用当前不使用但以后要使用的监视项。在调试过程中,Watch List中的许多有效监视项会减慢程序执行速度,因为每当一个代码行执行时,所有Watch List变量都要更新。

向Watch List中添加变量(Adding Variables to the Watch List)

可用多种方法往Watch List中添加监视项。最快速的方法是点击Code Editor中的变量名,然后从Code Editor的快捷菜单中选择【Debug | Add Watch at Cursor】或按【Ctrl + F5】键,该监视项就会被立即增加到Watch List中。如果需要,用户可以编辑该监视项,修改其属性。

image

要增加一个变量到Watch List中而又不想在源文件中找出该变量时,可从主菜单选择【Run | Add Watch】菜单项;当Watch Properties对话框弹出后,输入要增加到Watch List中的变量名并点击OK。

image

Note

虽然可将类实例变量添加到Watch List中,但显示的值可能无用。如下图:

image

应该使用Debug Inspector查看类的所有数据成员。

使用Watch List(Using the Watch List)

当碰到断点时,Watch List显示其中所有变量的当前值,如果当前没有打开Watch List窗口,可从主菜单【View | Debug Window | Watches】菜单项打开Watch List窗口。

image

Note

将Watch List窗口泊位到Code Editor窗口的底部,这样,在调试代码时,总可以看到它。

在某些情况下,Watch List中变量的后面会显示一条消息,而不是该变量的值。例如,如果一个变量不在作用域之外,或未找到,Watch List在该变量名后面显示“Undeclared identifier: ‘X’”;如果程序没有运行或不停在断点处,Watch List在所有的监视项后都显示[process not accessible]。禁用监视项后显示<disabled>。根据应用程序的当前状态或某个变量的当前状态,还可能显示其他消息。

就像上一章提到过的,用户在Watch List中偶尔会看到这样的显示:variable 'X' inaccessible here due to optimization,这是带优化功能的编辑器的一个小缺点。如果要检查易被优化的变量,则必须关闭编译器的优化功能,即把Project Options对话框中的Compiler页面上的Optimization选项关闭。

image

未被初始化的变量会显示随机值,直到它被初始化。

Note

Watch List可用作一个简单的十进制/十六进制转换器。要把一个十六进制数转换成十进制数,可从主菜单选择【Run | Add Watch】,在Expression字段输入十六进制数后点击OK,输入的十六进制数和与之等价的十进制数就会显示在Watch List中;要将一个十进制数转换成十六进制数,除点击Hexadecimal单选钮将显示类型改为十六进制外,其余操作都与前面相同。由于Expression接受数学表达式,因此还可以把Watch List当做一个十六进制计算器,甚至可以在同一个表达式中同时使用十六进制和十进制值。如下图:

image

这样使用Watch List只有一个缺点,应用程序必须停在一个断点处

在调试应用程序的过程中,Watch List是一个简单而又关键的工作。为了说明Watch List的使用,接下来做一个练习:

1)创建一个应用程序,在其主窗体上放置一个按钮。将按钮的Name属性设置为WatchBtn,Caption属性改为Watch Test。将主窗体Name属性改为DebugMain,Caption属性改为Debug Watch List Test。

2)双击按钮,会在Code Editor中显示按钮的OnClick处理事件,按下面的样子修改其OnClick处理程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
procedure TDebugMain.WatchBtnClick(Sender: TObject);
var
   S: string;
   X, Y: Integer;
begin
   X := Width;
   S := IntToStr(X);
   Y := Height;
   X := X * Y;
   S := IntToStr(X);
   X := X div Y;
   S := IntToStr(X);
   Width := X;
   Height := Y;
end;

3)保存该工程,将单元命名为DbgMain,工程命名为DebugTest。

4)在OnClick处理程序的begin语句之后的第一行上设置一个断点,运行该应用程序。

image

5)点击Watch Test按钮,调试器会停止在断点处。当调试器停在断点处时,IDE和Code Editor会显示在最顶层。

6)把变量S,X和Y增加到Watch List中(由于代码优化,变量X和变量Y在开始时是不可访问的),如下图:

image

7)安排好Watch List和Code Editor的位置,以便用户能同时看到两个窗口(不妨把Watch List泊位到Code Editor的底部)。

8)将输入焦点切换到Code Editor,并按F8执行下一行代码,执行完毕后,执行点移到下一行。此时Watch List中变量X显示一个值。如下图:

image

9)按F8继续一行一行执行程序,监视Watch List中变量的结果。

10)当执行点到达OnClick处理程序的最后一行时,点击工具栏中的Run按钮继续运行应用程序。

用户可反复点击Watch Test按钮来体会Watch List是如何工作的,每次还可试验不同监视设置的效果。

Note

在上面的例子中,OnClick处理程序先获取主窗体的Width属性和Height属性的值,接着执行一些计算,然后再将Width和Height设置成开始时的值。这段程序执行完后,什么都未发生改变。在该方法末尾给Width和Height属性赋值是有原因的。

如果在代码中不真正使用变量X和Y的话,用户就不能检查这两个变量,因为编译器在优化代码时会发现这个两个变量未被使用,从而将它们删除。在方法的末尾使用这两个变量就是为了避免编译器把它们优化掉。

前面提到过这个问题,希望大家对带优化功能的编译器的工作过程有个基本了解。这样,当开始调试应用程序,碰到诸如“Variable ‘Y’ inaccessible here due to optimization”一类的消息时就不会不知所措。


Delphi应用程序的调试(四)The Debug Inspector

调试检查器(The Debug Inspector)

Debug Inspector使用户能查看诸如类和记录的数据对象,也可以用它来查看整数、字符数组等简单数据类型,但这类简单数据类型最好是用Watch List查看。Debug Inspector最大用途是用于查看类和记录。

Note

只有在调试器下运行的程序暂停执行时,才能使用Debug Inspector。

要查看一个对象,点击Code Editor中该对象的名字,并从Code Editor的快捷菜单中选择【Inspect】菜单项或按【Alt + F5】,也可从主菜单选择【Run | Inspect…】菜单项。

Debug Inspector窗口包含所选对象的详细信息。如果要查看的对象时简单数据类型,Debug Inspector窗口就会先显示其当前值(十进制和十六进制两种格式),且窗口底部的状态行显示其数据类型。例如,要查看一个整型变量,该变量的值就会被显示出来,且状态行上显示“Integer”。在Debug Inspector窗口的顶部有一个组合框,它包含被查看对象的描述。

如果用Debug Inspector检查一个类,则Debug Inspector窗口如下图所示:

image

为了更好的理解Debug Inspector,请按下列步骤操作:

1)装入前面创建的DebugTest程序,下载:WatchList测试程序.rar

2)在WatchBtnClick方法的某个位置设置一个断点。如下图:

image

3)运行该程序,并点击Watch Test按钮。调试器会停在设置的断点处。

4)从主菜单【Run  | Inspect…】,显示Inspect对话框。

5)在Expression字段中输入Self,点击OK。

6)Debug Inspector被显示出来,此时用户可检查主窗体数据。

Note

只能从类的方法内部查看Self。如果偶然在常规函数或过程中设置断点,并试图查看Self时,系统会显示一条错误消息,告诉用户Self是一个非法符号。如下图错误信息:

image

上面的例子中,Self是应用程序的主窗体。

Debug Inspector页面(Debug Inspector Pages)

为了详细讲解Debug Inspector页面的各个部分,我们先来设计一个简单的类,步骤如下:

1)选择主菜单【File | New | Other】,选择Console Application(控制台程序),新建一个控制台程序;

2)创建一个父类Animal和子类Dog;如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
program DebugInspectorPage;
 
{$APPTYPE CONSOLE}
 
uses
   SysUtils;
 
type
   TAnimal = class
     Name: string;
   end;
   TDog = class(TAnimal)
     Color: string;
     procedure Say();
   end;
var
   Dog: TDog;
{ TDog }
 
procedure TDog.Say;
begin
   Writeln('汪汪...');
end;
 
begin
   Dog := TDog.Create;
   Dog.Name := '小黄';
   Dog.Color := '黄色';
   Dog.Say;
   Dog.Free;
end.

3)然后在end.结束前设置一断点,如下图:

image

4)保存该程序,保存工程为DebugInspectorPage.dpr;接下来运行该程序,在断点处停止后,选择【Run | Inspect】,增加一个Dog变量;

image

5)此时将显示出Debug Inspector页面,如下图:

image

Data页面中同时显示出了父类和子类的数据字段,如果用户只想查看子类的信息,可以点击右键,在弹出的菜单中勾掉【Show Inherited】菜单项即可,

image

勾掉后如下图:

image

6)如果要进一步查看一个数据成员,可以双击该数据成员所在行的值栏,会打开第二个Debug Inspector窗口,其中显示所选的数据成员。可同时打开多个Debug Inspector窗口。

image

7)Debug Inspector的Method页面显示类的方法。在某些情况下,Method标签页不显示(当显示查看简单数据类型时)。状态栏显示所选方法的声明。如下:

image

8)Debug Inspector的Properties页面显示被查看类的属性。查看类的属性价值不大(所提供的信息没有什么特别用处)。大多数时候,在Data页面上查看与某个属性相关的数据成员就能满足用户的需求。

Note

仅当用户检查类时,Debug Inspector的Method页面和Properties页面才有效。当检查简单数据类型时,值显示Data页面。

Tip

如果用户希望Debug Inspector窗口总在Code Editor的上面,可到主菜单【Tools | Debugger Options…】的“Debugger Options”对话框的General页面上,选中“Inspectors stay on top”复选框。如下图:

image

Debug Inspector快捷菜单(Debug Inspector Context Menus)

Debug Inspector窗口也有快捷菜单,用户在Debug Inspector查看数据对象时,可使用这个快捷菜单。

image

例如,用户可单击鼠标右键并从快捷菜单选择【Descend】菜单项,用选取的对象替换Debug Inspector窗口中的当前对象,而不必为每个对象打开一个Debug Inspector窗口。

再例如,要查看一个带有Button1按钮的窗体,可在Debug Inspector中选取Button1,并从快捷菜单中选择【Descend】项或按【Ctrl+D】键,Debug Inspector就会去查看Button1对象了。这样做的好处:IDE记录所有被查看过的对象,如果要回过头去看被查看过的对象,只需从Debug Inspector窗口顶部的组合框中选取对象即可。

【Change】菜单项用于改变变量的值。

Note

当用Debug Inspector改变变量的值时要特别小心。一旦改错了数据成员或给数据成员指定非法值,都可能导致程序失败。

【Inspect】菜单项使用户能再打开一个Debug Inspector窗口,显示光标当前选中的对象。

【New  Expression】菜单项使用户能输入一个新的表达式,用于Debug Inspector中检查。

【Show Inherited】菜单项决定Debug Inspector显示信息的多少。当【Show Inherited】被选中时,Debug Inspector中显示被检查类的所有数据成员、方法和属性,以及从祖先类中继承的数据成员、方法和属性。当【Show Inherited】没有被选中时,只显示被检查类本身的数据成员、方法和属性。关闭此菜单项可以加快Debug Inspector的速度,因为不用显示那么多的信息了。

Tip

如果用户忘记了类中某个数据成员的类型,可当程序暂停在断点时点击该数据成员,并按【Alt + F5】显示Debug Inspector。Debug Inspector窗口的底部状态栏显示该数据成员的数据类型。


Delphi应用程序的调试(五)其他调试工具

Delphi7中提供了一些附加调试工具来帮助用户检查程序错误。从性能上讲,其中一些工具属于高级调试工具。尽管高级调试工具不像其他工具那样常用,但对于经验丰富的编程人员来说,它们是非常有用的。

Evaluate/Modify对话框(The Evaluate/Modify Dialog Box)

该对话框用于检查变量的当前值和修改变量的值。使用这个对话框,用户可以修改某个变量的值来测试不同的输出结果。在调试期间改变一个变量的值,使用户能测试程序不同参数的效果,而不必每次都重新编译。如下图主菜单【Run | Evaluate/Modify】或按【Ctrl + F7】

image

Note

该对话框的工具栏即可显示大图标也显示小图标,要在大小图标进行切换的话,用鼠标拖动位于工具栏下方的线条,工具就会在大小图标间进行调整了。

image

Evaluate/Modify对话框,类似于Watch List和Debug Inspector。如果点击代码中的一个变量,并从Code Editor的快捷菜单中选择【Evaluate/Modify】菜单项,该变量会自动被求值。也可手动输入要进行求值的变量,从主菜单选择【Run  | Evaluate/Modify】菜单项,然后输入要求值的变量名。

Expression字段用于输入要对其求值的变量名或表达式。点击Evaluate按钮或按Enter键,表达式或变量就会被求值。结果显示在Result字段中。如下图:

image

Note

Evaluate/Modify对话框可当做一个简易计算器使用,可输入十六进制数(或十进制数,或两者都可)的数学公式,让计算器计算结果。例如如下图:

image

还可在Expression中输入逻辑表达式,Result显示True。如下图:

image

程序必须停在断点处才能使用Evaluate/Modify对话框这一功能。

如果用户想要改变一个变量的值,可在New Value字段输入新值并点击Modify按钮,变量就会变成输入的新值。当用户点击Run按钮重启启动程序(或继续步进调试)时,就会使用新值。

Note

与Watch List和Debug Inspector不同的是,当用户一行一行执行代码时,Evaluate/Modify对话框不会自动更新。如果代码改变了Evaluate/Modify对话框中变量的值,必须再点击Evaluate按钮才能看到改变后的值。这使得Evaluate/Modify对话框有个优点:步进式调试代码时速度更快,因为调试器不必每执行一行代码就求一个表达式的值。可交互地使用这个对话框来求变量或表达式的值,并且求完值后立即关闭此对话框。 

调用栈窗口(The Call Stack Window)

在程序运行阶段,用户可通过查看调用栈来检查应用程序调用的函数或过程。从主菜单上选【View | Debug Windows | Call Stack】菜单项来显示Call Stack窗口,该窗口列出应用程序调用的函数和过程,按调用顺序的先后排列,最近调用的函数或过程列在窗口顶部。

image

双击Call Stack窗口中的方法名,会显示该方法的代码行(如果该方法在应用程序中);当函数或过程的代码不存在时(VCL方法), Call Stack窗口显示该过程所在的模块名和地址。双击没有源代码的函数和过程,会显示CPU窗口。

当碰到Windows Access Violation错误时,查看调用栈非常有帮助。通过查看调用栈,用户能找出程序中产生错误的位置;找到程序中错误位置是排除错误的第一步。

Tip

如果调用栈列表中包含有无意义的信息,那可能是调用栈被破坏了。被破坏的调用栈通常标志着栈溢出或内存覆盖。 

CPU窗口(The CPU Window)

image

可从主菜单【View | Debug Windows | CPU】菜单项或按【Ctrl + Alt + C】来显示CPU窗口。 
image

CPU窗口使用户能够在汇编指令级查看应用程序。可以执行一个汇编指令就暂停一下;也可以运行程序至某条汇编指令(就像用常规调试器运行程序至某行源代码一样)。CPU窗口分成五个窗格:反汇编窗格(Disassembly pane)、寄存器窗格(CPU Registers pane)、标志窗格(Flags pane)、原始栈窗格(Machine Stack pane)和转储窗格(Memory Dump pane)。

每个小窗格都有一个快捷菜单,这个快捷菜单提供使用该窗格时所需的功能。要有效地使用CPU窗口,必须懂汇编语言。显然,CPU窗口是一个高级调试工具。

Go to Address命令(The Go to Address Command)

Go to Address命令也是一个高级调试工具。当应用程序出现故障时,Windows会显示一条出错消息,给出违例地址。用户可以使用Go to Address命令来找出程序中发生故障的位置。当Windows发出Access Violation出错消息时,会显示一个类似于下图的错误。

image

当用户看到这样的出错消息时,记下违例发生的地址,从Code Editor快捷菜单中选择【Debug | Go to Address】菜单项来显示Go to Address对话框。

image

把记下的地址输入到Go to Address对话框的Address字段中。点击OK,调试器就开始查找发生故障的源代码行。如果故障出现在代码中,则光标会指着产生错误的源代码行。如果是代码以外的地方发生故障,会弹出一个消息框告诉用户,代码中未找到该地址。这是一个高级调试工具,用户可能还从未使用过。


Delphi应用程序的调试(六)步进式代码调试

步进式代码调试(Stepping Through Your Code)

步进式代码调试是最基本的调试操作之一,但仍要在此讲述。人们常常容易犯只见树木不见森林的错误。经常复习基本的知识有助于读者了解以前不知道的东西。

调试沟槽符号(Debugging Gutter Symbols)

在开始讲述之前,先要说说在调试会话期间出现在Code Editor沟槽中的符号。在之前的讲解中讲过,当用户在一个代码行上设置一个断点,沟槽中就会出现一个红色的圆圈。

image

沟槽中还有一个绿色箭头符号指示执行点所在位置。如下图:

image

有一点没有讲过,就是在沟槽中与某些代码行对应的位置上有一些蓝色小点。这些蓝点指示实际产生汇编代码的源代码。如下图,调试器停在一个断点处时的Code Editor。其中有指示产生汇编代码的源代码行的蓝色小点,也有指示执行点的箭头符号,还有断点符号。断点符号上的复选标志表示该断点是一个有效断点。

image

仔细观察上面的代码,不带小点的代码行不产生任何编译代码。例如上面的:

1
2
3
var
   S: string;
   X: Integer;

为什么这几行不产生代码呢?因为它们是变量声明行。再看一行:

1
X := 20;

为什么这一行不产生代码呢?这是因为代码优化的缘故。编译器在编译代码时会发现变量X未实际使用过,从而将它优化掉。再看下面几行:

1
2
3
{$IFNDEF WIN32}
S := 'Something's very wrong here...';
{$ENDIF}
编译器不会编译器伪指令之间的源代码行进行编译,因为符号WIN32定义在一个Delphi7的程序中。编译器伪指令{$IFNDEF WIN32}告诉编译器:如果目标平台不是32位Windows,就编译这一行。因为Delphi7是32位编译器,所以不编译这行代码。如果是在Delphi1(16位环境)中,这行源代码就要编译。

步进式调试与跟踪(Step Over and Trace Into)

好了,再回到“步进式调试代码”上来。当程序在断点处暂停时,用户可以做很多事情:在Watch List中设置要监视的变量,用Debug Inspector检查对象或查看调用栈。还可以步进式调试代码,当每一个代码行执行时,监视变量和对象的变化。

当继续步进式调试时,会看到源代码中下一步要执行的源代码以蓝色加亮显示。如下图:

image

如果打开了Watch List窗口和Debug Inspector窗口,它们就会随着每一代码的执行而被更新。在Watch List和Debug Inspector窗口中能立即看到变量和对象的变化。IDE调试器有两个主要步进命令:Step Over和Trace Into。

1、Step Over

Step Over是指执行一行源代码,并在其下一行暂停。“Step Over”在此有点用词不当,因为从字面上理解,是跳过一个源代码行的意思。但是,此处不能从字面上去理解Step Over。实际上,Step Over是指执行当前源代码行,如果该行代码调用了函数或过程,则所调用的函数或过程也要完整地执行完。例如,一个程序的某行代码调用一个方法,在该代码行上设置一个断点;当用调试器Step Over该行代码时,调试器将执行完所调用的方法并停在下一行代码上。

要用Step Over调试程序,可以按F8键,也可以从主菜单上选【Run | Step Over】,或从工具栏中选择image

Note

当用户步进式调试程序中的各个源代码单元时,Code Editor会自动装入并显示所需的源代码单元(如果这些单元还未打开)。

2、Trace Into

当用户在步进式调试代码过程中碰到函数或过程时,Trace Into命令允许用户跟踪该函数或过程的执行。Trace Into不是像Step Over那样执行完函数或过程后返回到下一行,而是将执行点放置到所调用函数或过程的第一行源代码上,然后用户可以使用Step Over或Trace Into来逐步步进调试该函数或过程。Trace Into的快捷键为F7。

当用户检查完变量以及做完其他要做的调试工作后,可点击Run按钮再运行该程序,程序将会正常运行,直至碰到下一个断点。

Note

如果用户有专业版Delphi或客户/服务器版Delphi,那就可以跟踪VCL源代码。当碰到一个VCL方法时,Trace Into允许用户进入该方法的VCL源代码,用户可查看任何需要查看的变量。必须将VCL源代码所在目录的路径添加到Project Options对话框(Directories/Conditionals页面)上的Search Path字段中,如下图:

image

OK确认之后要重新编译、链接。跟踪VCL源代码对大多数编程人员可能意思不大;但对于经验丰富的程序员,它是非常有用的。

3、Trace To Next Source Line

另外一个调试命令是“Trace To Next Source Line”快捷键是【Shift + F7】。可从主菜单选择【Run | Trace to Next Source Line】菜单项打开该命令。

image

用户不会频繁使用这个命令,特别是调试和Windows编程还不太熟悉的用户。有些Windows API函数使用回调函数,意思是指Windows函数调用用户的函数来执行一些操作。

如果执行点在一个Windows API函数上,而这个函数使用一个回调函数,则使用Trace to Next Source Line命令会跳过执行点到回调函数的第一行。其效果类似于Trace Into(但在某些特定情况下,两者的效果却又完全不同。)。

当步进式调试一个方法时,执行点最终要到达该方法的end语句。若所调试的方法在其运行结束后将控制权返回给Windows,则当执行点在方法的end语句时按F8键,可退出该方法并把控制返回给正调试的程序。此时不能确定程序会不会再暂停,因为IDE具有输入焦点。要切回到该程序,将其激活就可以了。(点击其在Windows任务栏上的按钮)。

步进式代码调试是一个基本的调试技术,用户在调试程序时要经常使用这一技术,因此用户要记住有关的键盘快捷键:

【F7】Trace Into

【F8】 Step Over

【F9】 Run


Delphi应用程序的调试(七)调试DLL

调试DLL与调试可执行文件在大多数地方都是相同的。在DLL的代码中设置断点,当碰到断点时,调试器就会暂停执行DLL。通常是通过创建测试程序并在调试器下运行测试程序办法来测试DLL。

但是,有时候需要测试可执行文件使用的DLL,而可执行文件又是其他开发环境建立的。比如说,要建立一个供Visual Basic应用程序调用的DLL;肯定不能在Delphi调试器下运行一个VB应用程序,能做的只是告诉Delphi调试器,将该VB应用程序作为一个主应用程序来启动(自然,该主应用程序必须包含装载该DLL的代码)。通过Run Parameters对话框来告诉Delphi启动一个外部主应用程序。

要显示Run Parameters对话框,可从主菜单选【Run | Parameters】菜单项,在Host Application字段中输入EXE文件名,点击Load,主应用程序就会运行。Run Parameters对话框如下图所示:

image

主应用程序启动后,就可以像使用Delphi测试程序调试DLL一样来调试DLL:在DLL中设置断点,开始调试。

Note

Run Parameters对话框有一个Remote页面,这个标签用于为调试远程机器上的应用程序设置参数。远程调试属于高级调试内容,此处不做介绍,如下图所示:

image


Delphi应用程序的调试(八)事件日志窗口和模块窗口

事件日志窗口(The Event Log Window)

Event Log(事件日志)是一个专用的Delphi文件,它显示诊断消息,其中包括Delphi产生的诊断信息、用户程序产生的诊断信息、有时还有比如Windows自身产生的诊断信息。例如,Event Log包含被装入模块(大多是DLL)的信息:是否包含调试信息,启动应用程序的时间,停止应用程序执行的时间,碰到某个断点的时间等等。用户可通过Event Log窗口来查看Event Log。

从Delphi主菜单【View | Debug Windows | Event Log】菜单项来显示Event Log窗口。

image

如下图,给出了调试应用程序期间的Event Log窗口。

image

 

Event Log窗口有一个快捷菜单,如下图:

image

用户可通过快捷菜单来清除Event Log,将Event Log保存成一个文本文件,或增加注释到Event Log中。将Event Log存成文本文件,用户能更彻底地浏览该消息表,或查找某段具体的日志信息。Event Log的快捷菜单也有一个【Properties】菜单项,用户可以用它来进一步定值Event Log。当选择【Properties】菜单项时,会弹出一个对话框,让用户修改Event Log选项,这个对话框与Debug Options对话框中的Event Log页面一样。如下图:

image

用户可以通过Windows API函数OutputDebugString来将自己的消息发送到Event Log中。

 

模块窗口(The Module Window)

Module窗口显示当前装入的模块、附加到这些模块的源文件,以及从这些模块引出的符号(函数、过程和变量)。用户可从主菜单【View | Debug Windows | Modules】菜单项来调出Module窗口。Module窗口是一个高级调试工具,因此不在这里作详细介绍。大家应该花些事件实际使用Module窗口,看看它是如何工作的。如下图是实际使用中的Module窗口。

image


Delphi应用程序的调试(九)调试技术

这里还要再介绍几个调试技术。大家使用这些调试技术,能使调试程序的工作变得更容易。

OutputDebugString函数

当程序运行时跟踪程序的执行有时对用户是很有帮助的;也许用户希望在不使用断点来暂停程序执行的情况下查看变量的值。使用OutputDebugString函数就能做到这些。这个函数是个使用方便的调试工具,但很多程序员却忽视了它,主要原因是对它介绍的不够。观察下图中Event Log窗口的最后一个入口,这一入口是用下面的代码生成的:

1
2
3
4
procedure TForm1.btn1Click(Sender: TObject);
begin
   OutputDebugString('In the btn1Click method...');
end;

image

这就是全部要做的。由于Delphi是系统调试器,因此,任何用函数OutputDebugString发送的字符串都会出现在Event Log窗口。可以在代码中任何位置调用OutputDebugString函数。

要查看一个变量的值,必须按格式构成字符串,并把字符串发送给OutputDebugString函数,例如:

image

运行程序后,点击btn1后,Event Log中显示如下:

image

使用OutputDebugString函数可以查看程序运行的整个过程,即使是对实践要求严格的代码段。

 

追踪查找存取违例

当一个程序试图往不属于它的内存写入数据时,Windows会发出一条“Access Violation(存取违例)”出错消息。所有的Windows程序员在开发应用程序时,都碰到过存取违例错误。

Note

在16位Windows中使用术语一般保护性错误GPF(General Protection Fault)。这一术语在32位Windows中也很流行,尽管32位Windows实际上产生Access Violation出错信息,而不是GPF。

不论是初学者还是经验丰富的Windows程序员,要追踪查找存取违例,都是一件困难的事情。但是,随着编写Windows程序的经验积累,程序员会逐渐对存取违例原因的查找产生产生第六感。下面讲述一些线索供大家在查找违例时参考;并不是只有这些情况才会使程序产生存取违例,但它们是最常见的情况。

1、未初始化指针

未初始化指针是已经在程序中声明过的指针,但还未给它赋一个有意义的内存地址值。未初始化指针包含的是随机数据,最好的情况是它指向内存中无关紧要的地址,最坏的情况是它指向用户程序所在的内存中的某个单元,这样会导致不稳定的程序动作,因为每次运行程序时该指针可能指向不同的内存单元。应当在使用一个指针前和指针所指对象被删除之后将该指针设置成nil(空指针)。当存取一个空指针时,程序会停止运行并报存取违例,调试器加亮显示出错源代码行,这样用户就能立即查出有问题的指针。

2、删除前面已删除的指针

删除一个已经被删除的指针会导致存取违例。应该将已删除的指针设成nil(空指针);删除一个空指针是十分安全的。把删除过的指针设置成nil(空指针),再删除这个指针时就保证不会出错。

3、数组覆盖(Array Overwrites)

覆盖一个数组的末尾可引起存取违例。在有些情况下,被覆盖的内存不是关键性的,不会马上显现出问题,但过后不久程序还是因故障而停止运行。当这种情况发生时,用户很可能到程序停止运行的地方去查找故障,但问题实际上是出在程序的其他地方。另外一种情形是:被覆盖的内存很关键,因而程序会因故障而立即停止运行。极端情况下会造成Windows被破坏。

可通过范围检查把数组覆盖的可能性减少到最低程度。当设置检查范围时(缺省设置),编译器会对每一次数组引用作检查,看看看所存取的数组元素是否超出了有效范围。例如,下面这段代码就会导致编译器报错:

image

这段代码中要存取一个数组的30号元素,而此数组只有21个元素。编译器会检查出被存取的数组元素超出了数组声明的范围,并产生一个编译器错误,出错信息如下:

image

但是,检查范围对变量无效。例如,下面的代码就不会导致编译报错:

image

在这段代码中,尽管数组覆盖了9个字节,却不会产生编译错误;这是因为在编译时,编译器不知道变量X的值。

4、程序终止时存取违例

当正常关闭一个程序时发生存取违例,一般都说明堆栈设置的太小。尽管在32位程序中这种情况发生的可能性不大,但在极端情况下也会发生。就像前面讲过的删除一个已被删除的指针,也可能引起程序终止时存取违例。

调试快速提示

除前面给出的许多提示外,还要补充一下提示:

  • 改变窗体的Caption属性,从而不必使用断点就能显示变量。因为在窗体上添加Label组件是件很容易的事情,因此用户可使用Label组件,改变Label组件中的正文来显示变量的值或其他要显示的信息。
  • 启用一个条件断点或数据监视断点来临时减慢程序的运行速度(比如要让程序缓慢运行以便查看程序效果)。当程序运行碰到断点时,要检查断点条件,从而减慢程序的执行。
  • 在程序运行时,使用Evaluate/Modify对话框临时改变一个变量的值。这样,用户可查看不同值对程序的影响,而不必每次重新编译代码。
  • 从主菜单上选择【Run | Inspect】,并在Expression字段输入Self,来检查调试器当前暂停处的类。
  • 使用MessageBeep($FFFF)作为发生指示器,来指示程序执行到达程序中的某一位置。当用参数$FFFF时,它会使PC的扬声器发出嘟嘟声。
  • 从主菜单上选择【Run | Program Reset】菜单项或按【Ctrl + F2】键来终止出错调试过程。
  • 使用中间变量来断开长等式或连锁方法调用,以便用户能更方便地检查结果。
  • 使用ShowMessage,MessageBox或MessageDlg函数来显示程序跟踪信息(ShowMessage函数用来更方便,因为它只有一个字符串参数)。

Caution

如果用户在Windows 95上运行Delphi,则要尽量少使用Program Reset选项。有些时候,使用Program Reset终止应用程序的运行会破坏Windows 95。

但不是所有的Windows 95都会出现这种情况,因此可能不会遇到这个问题。Windows NT发生这种问题的可能性更小,因此在Windows NT中可以放心地使用Program Reset。就其个人而言,本人只在调试的应用程序被锁死时才使用Program Reset。

还有一个提示就是,当调试程序时,可使用一个内存检查程序。第三方的内存检查程序用于检查用户应用程序有无内存泄露。当用户将应用程序投入实际使用时,这类程序能省去许多麻烦。当应用程序存在内存泄露时,在使用该应用程序的过程中就会出问题。早起发现并排除内存泄露,无疑可大大节省用户的时间和精力。


Delphi应用程序的调试(十)调试器选项

可在两个级别上设置调试选项:工程级和环境级。在前面的讲解中讲解了工程级调试选项,通过主菜单【Project | Options…】打开如下对话框:

image

 

可在Debugger Options对话框中设置全局级调试选项。从主菜单【Tools | Debugger Options】菜单项调出Debugger Options对话框。

image

在Debugger Options对话框的底部有一个标记为Integrated debugging的复选框,它控制是否使用IDE调试器调试程序。如果选中Integrated debugging复选框,则使用IDE调试器;如果不选中这个选项,则不使用IDE调试器;这意味着当用户点击Run按钮时,程序会执行,但调试器失效,因此所有断点均不起作用。

调试器选项对话框有四个页面:General,Event Log, Language Exceptions,OS Exceptions。下面将分别介绍:

1、通用(General)页面

General页面是用户设置通用调试选项的地方,如下图:

image

【Map TD32 keystrokes on run选项】告诉Code Editor使用Turbo Debugger中使用的键击映射(Turbo Debugger是Borland公司的一个单独调试器)。如果用户长期使用Turbo Debugger,并且对它的键映射很熟悉,那么该选项不失为一个好工具。

当程序在调试器下运行时,【Mark buffers read-only on run选项】将Code Editor缓冲区设置成只读缓冲区。这样,在调试器下启动程序后,就不能再编辑源代码,直至程序终止运行。如果要在调试器期间修改源代码,则要将此选项关闭。

【Inspector stay on top选项】控制着Debug Inspector窗口是否总位于Code Editor的上面。这时一个好特性,因为当用户步进式调试代码时,多数时候都希望Debug Inspector窗口在Code Editor的上面。

当程序运行在调试器下面时,【Rearrange editor local menu on run选项】改变Code Editor快捷菜单的外观。选中此选项,Code Editor菜单中调试专用菜单项移到菜单顶部,以方便用户选用。

image不选中状态菜单

image选中状态的菜单

 

2、事件日志(Event log)页面

Event Log页面用于设置Event Log选项。可以选择一个数来限制同一时间Event Log中可出现的消息条数,也可以不作限制。还可以在Event Log中选择想看的消息的类型。

image

 

3、语言异常(Language Exceptions)页面

image

此页面用于控制调试器碰到的VCL异常的类型。本页面上最重要的选项是【Stop on Delphi Exceptions选项】。当选中此选项时,如果出现异常,调试器就会暂停程序执行。当关闭此选项时,调试器就以普通方式处理VCL异常,即弹出一个消息框通知用户程序所出现的错误。

Note

当选中【Stop on Delphi Exceptions选项】时,调试器碰到异常就会暂停,不管用户程序中是否对该异常做了处理。如果不希望调试器每碰到一个异常都停止,就关闭此选项。这个选项相当于老版本Delphi中的【Break on exception选项】。

【Exception Types to Ignore选项】用于指定被调试器忽略的异常事件的类型。在本表中列出的所有异常事件类型都被调试器忽略,并以缺省方式处理。这与关闭【Stop on Delphi Exceptions选项】的效果一样。

要往表中增加异常事件类型,点击Add…按钮并输入异常事件类型名称。例如,要通知调试器忽略“被0除”异常事件,可点击Add按钮,并在Exception Type字段输入EDivByZero。如下图:

image

添加到该列表中的异常事件类型适用于所有工程。

 

4、OS(操作系统)异常页面

该页面控制调试器或用户程序是否处理操作系统异常事件。如下图:

image

当【Handled by选项】设为User program时,碰到异常事件,调试器就中断程序执行。当这个选项被设为Debugger时,以普通方式处理VCL异常,即弹出一个消息框通知用户程序中发生的错误。

Note

当把【Handled by选项】设置成Debugger时,调试器一碰到异常事件就会中断程序运行,不管用户程序是否对异常事件做了处理。如果不希望调试器每碰到一个异常事件就中断,则要将此选项设为User Program。这个选项相当于老版本Delphi中的【Break on exception选项】。

【On resume】选项确定当重新恢复程序执行后,如何处理异常事件。

Exceptions列表框中列出了可能的操作系统异常事件。要为某个类型设定选项,点击Exceptions列表中该异常事件类型,然后按要求设定Handled by和On resume选项。Exceptions列表框左边缘的符号指示异常处理和恢复执行设定。如下图:

image

 

小结

调试程序是一项无休止的任务。调试程序不单单是指查程序中的故障。精明老练的程序员在开始创建新工程时就开始学习使用调试器。调试器既是开发工具又是查找故障的工具。大家还要多花时间实际使用调试器,才能精通它。就从现在开始吧。


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值