第8章 异常处理与程序调试
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
对象再次扔出。
第8章
异常处理与程序调试
【例8-2】
类似例8-1使用两个编辑框和一个按钮,
按钮执行的任务是将两个编辑框的内容转换为一个整 数和一个浮点数,并将二者相除得到平均工资。该程
序运行时,除了可能发生类型转换的错误外,还可能
发生因除数为0引起的错误。假定程序设计时已预见到 前一种类型的错误,但未预见到第二种错误。为保险 起见,可以将Button1的OnClick事件代码编写如下:
ERegistryException
EStackOverflow EZeroDivide
注册表操作时的错误
栈溢出 在浮点数相除时用零作为除数
第8章
异常处理与程序调试
8.2 异 常 处 理
BCB支持ANSI C++的异常处理机制,对于常见的 硬件错误、输入/输出错误、使用VCL组件时产生的错 误等在BCB中都有相应的异常类,应用程序一般只要 能捕捉到这些异常类并作相应的处理即可。
Edit1->Text = "";
Edit2->Text = ""; Label3->Caption = "金额:"; Edit1->SetFocus ( ); ShowMessage ("输入数据格式错误!");
}
}
第8章
异常处理与程序调试
图8-2为修改后的程序在输入了同样的数据时执行 按钮命令所见到的画面。我们看到的是更为友好的中 文提示信息,而且编辑框中的错误内容已被程序清除。
转换错误引起,我们只要捕捉特定的EConvertError异
常类即可。下面是改写后Button1的OnClick事件代码:
第8章
异常处理与程序调试
void__fastcall TForm1::Button1Click (TObject *Sender)
{ try { int i = StrToInt (Edit1->Text);
第8章
异常处理与程序调试
【例8-1】 建立一个应用程序项目,在Form1中放入 两个TEdit编辑框、三个标签和一个命令按钮。编辑框 Edit1和Edit2分别供用户输入数量和单价,其中数量应 输入整数。按钮的功能是根据数量和单价计算交易总 金额并通过标签输出。如果不考虑异常处理问题,只 要为Button1的OnClick事件编写如下简单的代码即可:
第8章
异常处理与程序调试
ANSI C++定义了try和catch关键字,为实现异常处 理机制提供了语法上的支持。BCB将异常作为某种对 象,定义了若干异常类,它们的基类是exception类。 表8-1列出了BCB定义的部分异常类。
第8章
异常处理与程序调试
表8-1 BCB中常用的部分异常类
异 常 类 名 称 EConvertError EDatabaseError EDBEditError EDivByZero EInOutError EIntOverflow 产生异常的原因 字符串或对象转换中产生的错误 访问数据库时产生的错误 编辑数据库字段时类型不兼容 在整除时用零作为除数 输入输出错误 整型变量上溢
第8章
异常处理与程序调试
8.2.4 使用try/__finally语句
BCB 扩 展 的 另 一 个 关 键 字 是 __finally , 可 用 于 try/__finally语句,它类似于Delphi中的try/finally语句。 不管是否发生了异常,位于__finally之后的代码块都要 执行。 注意:在try/__finally结构中不能使用catch。 下面是一个简单的例子。
使该信息不出现。
第8章
异常处理与程序调试
图8-3 BCB的IDE在出现异常时提供的信息
第8章
异常处理与程序调试
(2) catch (EConvertError& info)说明了需捕捉的异
常类型为EConvertError的引用并定义了变量info,使其 能捕捉EConvertError类异常,这是通常的用法。info可 在程序中作为EConvertError类的对象被引用,以获得 与异常有关的进一步信息。我们可以在 CatchStatements范围内使用info.Message和 info.HelpContext,前者代表一个BCB定义的错误编号, 后者是一条简短的错误信息。 (3) 为防止程序中发生输入格式错误的较好方法是 将 TEdit 控 件 换 成 TMaskEdit , 本 例 仅 以 此 说 明 有 关 try/catch语句的用法。
如果用户定义了自己的异常类,那么一定要在程
序中适当的地方使用throw来启动该异常。用户定义的 异常类和系统原有的异常类可以同样地被catch语句捕 获。对于被catch语句所捕获的异常,一旦需要,可以 在CatchStatements中再次使用throw扔出,以便启动另 外一个catch语句或缺省的异常处理程序。 throw语句可以带一个参数,该参数通常是一个异 常类的对象。也可以不带参数,表示将当前被捕获的
{ Edit1->Text = "";
Edit2->Text = "";
Edit1->SetFocus ( ); throw; } }
第8章
异常处理与程序调试
程序中使用了两个catch语句,第一个catch捕捉并 处理EConvertError类型的错误;第二个catch的类型说 明为“...”,表示捕捉除EconvertError外的所有异常。 但由于它不知道此时发生了什么异常,所以在清理了 编辑框的输入并设置输入焦点后,即调用throw再次扔
第8章
异常处理与程序调试
该程序计算limit的阶乘,若输入到Edit1中的数值 大于34会引起结构化异常 EXCEPTION_FLT_OVERFLOW。程序能捕获该异常, 并进行适当的处理。_fpreset函数可清除浮点数单元的 溢出状态。没有这一句,程序的行为不可预料。 注 意 : _fpreset 以 一 个 “ _” 开 头 , 而 __except 是 BCB的一个扩展关键字,它以两个“_”开头。
出异常给系统作缺省的处理。
第8章
异常处理与程序调试
8.2.3 使用try/__except语句
Windows有其自身的异常处理机制,由该机制产 生的异常被称为Win 32结构化异常。一般来说,BCB 应用程序不必直接处理结构化异常。但是在特殊情况 下BCB未能将结构化异常转换为相应异常类对象或不 能正确判断错误的原因,此时应用程序可以直接捕获 并处理结构化异常。BCB程序中可使用try/__except语 句处理结构化异常。此外,还提供了可与try/__except
for (int i = limit; i>1; --i) value*= (float) i; //计算阶乘
Edit2->Text = String (value);
} __except (GetExceptionCode ( )==EXCEPTION_FLT_OVERFLOW) { Label1->Caption = "溢出"; _fpreset ( ); }
第8章
异常处理与程序调试
图8-2 程序捕捉并处理了异常
第8章
异常处理与程序调试
【评析】 (1) 如果在BCB IDE下运行本例程序,那么在出现 如图8-1和图8-2所示的画面之前会先出现如图8-3所示 的画面,这是IDE为程序调试提供的信息。我们可以修 改IDE的有关设置或者在Windows下直接运行.exe程序
第8章
异常处理与程序调试
第8章 异常处理与程序调试
8.1 异常及产生原因 8.2 异常处理 8.3 程序的调试 8.4 程序中常见的错误 习题
第8章
异常处理与程序调试
8.1 异常及产生原因
发现错误有多种方法,主要是通过广泛地测试。 但软件工程的有关理论表明,测试一般不可能发现所 有的错误。何况测试是在特定软硬件环境下进行的, 因而会受到许多限制。异常处理是对可能出现的错误 进行预防,一旦发生即可迅速捕获,根据预先制定的 方案对现场作处理,尽可能避免损失并及时准确地将 发生的情况向用户报告或记录到日志中去。
EInvalidGraphic
企图处理不能识别格式的图形对象
第8章
异常处理与程序调试
企图对一个无效指针操作 与菜单项有关的错误 与ActiveX控件连接时错误 OLE自动化操作的错误 打印时产生的错误 错误地设置一个对象的属性
EInvalidPointer EMenuError EOleCtrlError EOleError EPrinterError EPropertyError
配合使用的函数GetExceptionInformation、
GetExceptionCode等。try/__except的使用类似try/catch。 下面是一个简单的例子。
第8章
异常处理与程序调试
float value=1.0;
try {
int limit = StrToInt (Edit1->Text);
float x = StrToFloat (Edit2->Text);
float y = x*i; Label3->Caption = "金额:"+FloatToStrF (y, ffCurrency, 10, 2); }
第8章
异常处理与程序调试
catch (EConvertError& info) {
第8章
异常处理与程序调试
void__fastcall TForm1::Button1Click (TObject *Sender)
{ try { int i = StrToInt (Edit1->Text);
float x = StrToFloat (Edit2->Text);
float y = x / i; Label3->Caption = " 平 均 工 资 : "+FloatToStrF (y, ffCurrency, 10, 2); }
第8章
异常处理与程序调试
catch (EConvertError& info)
{ Edit1->Text = ""; Edit2->Text = ""; Edit1->SetFocus ( );
Leabharlann Baidu
ShowMessage ("输入数据格式错误!");
return; } catch (...)
第8章
异常处理与程序调试
}
第8章
异常处理与程序调试
这一段程序确实很简单,但如果输入到编辑框的 内容不正确,则执行按钮命令时可能会发生异常。图 8-1为在数量框内输入了“2.08”,因而在将字符串转换 为整型值时发生错误并引起系统警示。
第8章
异常处理与程序调试
图8-1 程序发生异常
第8章
异常处理与程序调试
现在使用try/catch语句捕捉异常,并对捕捉到的异 常进行处理。由于可以预料到发生的异常由数据类型
TryStatements中的语句。如果在执行TryStatements期间 发生了TypeToCatch类型的异常,则不再执行
TryStatements中尚未执行的语句而转为执行
CatchStatements中的语句。 如果TryStatements中可能产生的异常多于一种,那 么可以使用若干连续排列的catch结构,其中的每个catch 结构用于捕捉一种特定的异常。TypeToCatch除了可以 引用BCB定义的各种异常类外,也可以引用用户定义的 异常类,还能使用“...”,表示可捕捉所有的异常类。
第8章
异常处理与程序调试
void__fastcall TForm1::Button1Click (TObject *Sender) {
int i = StrToInt (Edit1->Text);
float x = StrToFloat (Edit2->Text); float y = x*i; Label3->Caption = "金额:"+FloatToStrF (y, ffCurrency, 10, 2);
第8章
异常处理与程序调试
8.2.1 使用try/catch语句
BCB使用ANSI C++的try/catch语句捕捉异常,它的语法如下: try { TryStatements
}
catch (TypeToCatch) { CatchStatements }
第8章
异常处理与程序调试
try关键字表示try块的开始,此时程序执行
第8章
异常处理与程序调试
8.2.2 throw异常 ANSI C++使用throw关键字扔出(启动)异常。程序 在扔出异常后即被中断执行,如果此时有一个catch语 句捕获了该异常,则由该catch语句 CatchStatements进 行处理,否则由系统启动缺省的异常处理程序。
第8章
异常处理与程序调试