第十二章-异常处理与程序调试(一)(1)

在应用程序开发中如何检测、处理程序的运行错误是一个很重要的问题。在 Delphi 的集成开发环境( IDE )中提供了一个完善的内置调试器,可以帮助你发现大部分程序错误。但并不是所有的错误都可以被发现,而且当程序涉及到与外设的数据交换或操作外设,如要求用户输入、读写磁盘等时,错误的发生是程序无法控制的,如输入非法字符、磁盘不能读写等。这些情况不仅会导致应用程序异常中止而且可能引起系统的崩溃。针对这些问题,Delphi同时提供了一套强大的异常处理机制。巧妙地利用它,可以使你的程序更为强健,使用更为友好。

虽然Delphi为应用程序提供了一套缺省的自动异常处理机制,即当前模块发生错误后退出当前模块并给出错误信息,而并不立即引起应用程序的中止。但当应用程序执行的过程性很强时,仅仅利用这种方法是不够的,而且很容易导致程序执行的不可预测性。 

12.1 Delphi异常处理机制与异常类 

Delphi异常处理机制建立在保护块(Protected Blocks)的概念上。所谓保护块是用保留字try和end封装的一段代码。保护块的作用是当应用程序发生错误时自动创建一个相应的异常类(Exception)。程序可以捕获并处理这个异常类,以确保程序的正常结束以及资源的释放和数据不受破坏。如果程序不进行处理,则系统会自动提供一个消息框。

异常类是Delphi异常处理机制的核心,也是Delphi异常处理的主要特色。下面我们对异常类的概念和体系进行详细的介绍。

Delphi提供的所有异常类都是类Exception的子类。用户也可以从Exception派生一个自定义的异常类。

Exception类的定义如下,对于不常用的成员没有列出。  

{SysUtils 单元中}

Exception = class(TObject)

private

FMessage: PString;

FHelpContext: Longint;

function GetMessage: String;

procedure SetMessage(const Value: String);

public

constructor Create(const Msg: String);

constructor CreateFmt(const Msg: String; const Args: array of const);. . .

destructor Destroy; override;

property HelpContext: Longint

property Message: String;

property MessagePtr: PString;

end; 

Exception的一系列构造函数中最重要的参数是显示的错误信息。而数据成员中最重要的也是可被引用的消息字符串(message,messagePtr)。 这些信息分别对自定义一个异常类和处理一个异常类有重要作用。

Delphi提供了一个很庞大的异常类体系,这些异常类几乎涉及到编程的各个方面。从大的方面我们可以把异常类分为运行时间库异常、对象异常、部件异常三类。下面我们分别进行介绍。 

12.1.1 运行时间库异常类(RTL Exception) 

运行时间库异常可以分为七类,它们都定义在SysUtils库单元中。 

12.1.1.1 I/O异常 

I/O异常类EInOutError是在程序运行中试图对文件或外设进行操作失败后产生的,它从Exception派生后增加了一个公有数据成员ErrorCode,用于保存所发生错误的代码。这一成员可用于在发生I/O异常后针对不同情况采取不同的对策。

当设置编译指示{$I- } 时,不产生I/O异常类而是把错误代码返回到预定义变量IOResult中。 

12.1.1.2 堆异常 

堆异常是在动态内存分配中产生的,包括两个类EOutOfMemory和EInvalidPointer。

表12.1  堆异常类及其产生原因

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

异常类 引发原因

─────────────────────────────────

EOutOfMemory 没有足够的空间用于满足所要求的内存分配

EInvalidPointer 非法指针。一般是由于程序试图去释放一个业已释放的指针而引起的

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 

时间: 2024-10-30 09:38:44

第十二章-异常处理与程序调试(一)(1)的相关文章

第十二章-异常处理与程序调试(二)(5)

12.4 程序调试简介 Delphi提供了一个功能强大的内置调试器(Integrated Debugger), 因而对程序的调试不用离开集成开发环境(IDE)就可以进行. 程序错误基本可以分为两类,即运行时间错和逻辑错.所谓运行时间错是指程序能正常编译但在运行时出错.逻辑错是指程序设计和实现上的错误.程序语句是合法的,并顺利执行了,但执行结果却不是所希望的. 对于这两类错误,调试器都可以帮助你快速定位错误,并通过对程序运行的跟踪和对变量值的监视帮助你寻找错误的真正原因和解决错误的途径. 程序调试

第十二章-异常处理与程序调试(三)(2)

12.4.4.1 监视表达式 监视列表窗口(Watch List Window)显示程序运行中当前监视表达式的值. 选择View|Watches可以打开监视列表窗口. 从Code Editor中添加一个监视表达式最方便的方法是: 1.选中要监视的表达式: 2.从Code Editor加速菜单中选择Add Watch把表达式添加到监视列表窗口. 也可以利用下面的方法产生一个监视表达式: 1.用下列方法之一打开监视属性对话框(Watch Properties Dialog Box): ●主菜单中选择

第十二章-异常处理与程序调试(三)(1)

12.4.3 断点的使用 12.4.3.1 设置断点 设置断点首先在Code Editor中选定你想设置断点的代码行,而后进行如下的任一种操作: ● 单击选定代码行左边的空白 ● 按F5 ● 选择Code Editor加速菜单的Toggle BreakPoint项 ● 选择Run|Add Breadpoint打开断点编辑对话框(Edit BreakPoint Dialog Box),而后选择New去确认一个新的断点设置或选择Modify去对一个存在的断点进行修改 ● 从BreakPoint Li

第十二章-异常处理与程序调试(二)(4)

12.3.6 利用异常响应编程 利用异常处理机制不仅能使程序更加健壮,而且也提供了一种使程序更加简捷.明了的途径.事实上,使用自定义异常类就是一种利用异常响应编程的方式.这里我们再讨论几个利用标准异常类编程的例子. 比如为了防止零作除数,可以在进行除法运算前使用if-then-else语句.但如果有一系列这样的语句则繁琐程度是令人难以忍受的.这时候我们可能倾向于使用EDivByZero异常.例如如下一段程序就远比用if-then-else实现简捷明了. function Calcu(x,y,z,

第十二章-异常处理与程序调试(二)(3)

12.3.5.1 定义异常对象类 异常是对象,所以定义一类新的异常同定义一个新的对象类型并无太大区别.由于缺省异常处理只处理从Exception或Exception子类继承的对象,因而自定义异常类应该作为Exception或其它标准异常类的子类.这样,假如在一个模块中引发了一个新定义的异常,而这个模块并没有包含对应的异常响应,则缺省异常处理机制将响应该异常,显示一个包含异常类名称和错误信息的消息框. 下面是一个异常类的定义: type EMyException = Class(Exception

第十二章-异常处理与程序调试(二)(2)

12.3.3 响应一族异常 诸如 on ExceptionType do 的异常响应语句不仅可响应本类异常,而且可以响应子类异常.对于象EIntError.EMathError等系统不会引发的异常,它们将只响应其子类异常.而对于象 on Exception do 这样的语句将会对任何异常进行响应. 下面一段代码对整数越界异常进行单独处理,而对其它整数异常进行统一处理: try {整数运算} except on ERangeError do {越界处理} on EIntError do {其它整数

第十二章-异常处理与程序调试(二)(1)

异常响应为开发者提供了一个按自己的需要进行异常处理的机制.try -except -end形成了一个异常响应保护块.与finally不同的是:正常情况下except 后面的语句并不被执行,而当异常发生时程序自动跳到except,进入异常响应处理模块.当异常被响应后异常类自动清除. 下面的例子表示了文件打开.删除过程中发生异常时的处理情况: uses Dialogs; var F: Textfile; begin OpenDialog1.Title := 'Delete File'; if Ope

第十二章-异常处理与程序调试(一)(5)

12.1.3 部件异常类 12.1.3.1 通用部件异常类 通用部件异常类常用的有三个:EInvalidOperation.EComponentError.EOutOfResource.其中EInvalidOperation.EOutOfResource在Controls单元中定义:EComponentError在Classes单元中定义. 1.非法操作异常 EInvalidOperation EInvalidOperation 引发的原因可能有: ● 应用程序试图对一个Parent属性为nil

第十二章-异常处理与程序调试(一)(3)

12.1.1.4 浮点异常 浮点异常是在进行实数操作时产生的,它们都从一个EMathError类派生,但与整数异常相同,程序运行中引发的总是它的子类EInvalidOp.EZeroDivide.EOverFlow.EUnderFlow. 表12.4 浮点异常类及其引发原因 ━━━━━━━━━━━━━━━━━━━━━━━━ 异常类 引发原因 ──────────────────────── EInvalidOp 处理器碰到一个未定义的指令 EZeroDivide 试图被零除 EOverFlow 浮