delphi 下 用assert 来完成错误的捕捉
第6章Delphi程序异常处理与调试技术.

第六章程序异常处理与调试技术在Delphi中有两种程序错误,一种是编译错误,在程序编辑阶段就可以由编译器发现并给出提示。
另外一种是运行错误,这类错误不能在编译阶段查出,只能在程序执行时发现,称为运行错误。
Delphi提供了一种机制来处理运行错误,保护程序的正常执行,这种机制就是异常处理。
异常处理的方法是把正常的执行程序同错误的处理程序分离开来,这样可以保证在没有错误时,程序正常执行,当发生错误时,执行错误处理部分的程序,然后程序跳出保护模块,继续执行后续的程序。
6.1 Object Pascal异常的种类异常的种类:Delphi内建的异常类,程序员自定义的异常类。
异常基类及其属性和主要方法:在Delphi中,所有异常的基类是Exception 类。
所有其他异常类都是由该类派生而来。
1. exception属性该类有两个基本属性:HelpContext和Message。
(1)Exception.HelpContext属性该属性的定义如下:▪Type ThelpContext= -MaxLongint..MaxLongint;▪Property HelpContext:ThelpContext;HelpContext是ThelpContext类的一个实例,它提供了与异常对象联系在一起的上下文相关帮助信息的序列号。
该序列号决定当发生异常时用户按F1键显示的一个异常错误的帮助信息。
(2)Exception.Message属性该属性的定义如下:property Message: string该属性存储异常发生时的错误信息。
可以通过该属性在提示错误对话框中显示错误信息字符串。
2.exception方法(1)Exception.Create方法该方法的定义形式为:Constructor Create(Const Msg: String);该方法用来产生一个带有一条简单提示信息的对话框,对话框中的提示内容由Msg提供(2)Exception.CreateFmt方法该方法的定义格式如下:Constructor CreateFmt(Const Msg:String;Const Args:Array of Const) ;该方法用来产生一个带有格式化字符串提示信息的对话框,格式化的字符串由Msg和Args数组共同提供,其中数组Args负责提供用于格式化的数值。
Delphi中的异常处理

Delphi中的异常处理一.异常的来源在Delphi应用程序中,下列的情况都比较有可能产生异常。
1.文件处理2.内存分配3.windows资源4.运行时创建对象和窗体5.硬件和操作系统冲突6.网络问题7.数据库8.控件中的异常9.DLL文件的异常10.强制类型转换…………二.异常的处理1.try...except...end;在try 体内的代码发生异常时,系统将转向except 部分进行异常的处理。
这是Delphi 处理异常的最基本的方式之一。
只有当try 体内的代码发生异常时,才会跳转到except 里面的代码进行执行2.try...finally...end;这种异常处理结构一般用于保护windows的资源分配等方面,它确保了无论try 体内的代码是否发生异常,都需要由系统进行最后的统一处理的一些Windows对象的正确处理和try...except...ebd不同,该结构的finally部分总被执行3.不存在try...except...finally...end 结构来既处理异常,又保护资源分配的结构,但是,try...except...end结构允许嵌套到try...finally...end结构中,从而既处理异常,又保护资源的分配三.异常的精确处理1.定义一个异常在Delphi中,每个异常都是Exception类的一个派生类。
因此,定义一个异常就是定义一个Exception类的派生类当然,基类可以是Exception或者是Exception的任何一个任何层次的派生类2.在程序中抛出一个异常根据不同的情况抛出异常是使用异常的最基本的模式。
在Delphi中,由raise语句来实现raise 异常类.Create('异常信息说明');注意因为使用了异常类.Create('异常信息说明'); 所以也就是在内存中创建了一个异常实体。
或者直接使用:raise;看一个代码示例上面的代码可能会抛出异常,假如这是一个函数,那么在编程时候如果调用了这个函数的话不要忘记了要捕捉这个异常!建议用法建议使用raise 异常类.Create('异常信息说明');这样的方式,以及另外两个相似的语法方式,因为这样可以在抛出异常的时候尽可能详细的说明异常的情况,那么以后在捕捉异常的时候就可以又比较多的信息来让我们了解到异常出现的地方,如果直接使用raise;的话在except中使用raise 的时候,执行完raise的代码之后,在except中的且在raise后的代码将不会执行,它会在执行完raise 的代码后直接跳出except,例程这个代码例子,如果出现异常之后,会进入except,执行完raise之后将不会执行ShowMessage的语句,而是直接跳出,所以在编程的时候一定要注意!!如果想要在except中执行的代码,一定要放在raise的前面!!3.在try...except...end中更加精确的捕捉异常可以使用on E:异常类do...结构可以在do 体内处理特定异常类所抛出的异常。
Delphi异常处理机制

Delphi异常处理机制Delphi的异常处理⽅式有两种:try...except...end;try...finally...end;。
try...except主要⽤于捕获异常,只有出现异常的时候才会执⾏except部分。
try...finally主要⽤于资源释放,⽆论try语句块是否有异常都会执⾏finally语句块。
如下⾯的代码:tryraise exception.create('发现异常'); //在try语句块中抛出⼀个异常excepton e:Exception do//捕获异常beginshowMessage(e.message);end;end;⽤try..except是不会出现异常提⽰信息的对话框,需要⾃⼰主动去show出异常信息。
⽽try..finally.则会出现异常提⽰信息。
try..except和try..finally可以相互嵌套。
使⽤on e:Exception do可以精确处理特定的异常。
Exception是所有异常类的基类,Delphi内部就定义了处理常见异常的异常类(在SysUtils单元中),也可以从Exception继承定义⾃⼰的异常类使⽤raise语句可以抛出⼀个异常:EMyException=class(Exception)end;trytryraise EMyException.Create('我⾃⼰的异常');excepton e:EMyException doshowMessage(e.message);end;finallyshowMessage('我始终被执⾏');end。
assert函数用法

assert函数用法1. 什么是assert函数在编程中,assert函数被用于断言一个条件是否为真。
当给定的条件为假时,assert函数会抛出AssertionError异常。
它是一种用于调试和测试的工具,可以用来检查前置条件、后置条件、循环不变量等。
使用assert函数可以提前捕捉到程序中的错误条件,从而加快调试和定位错误的速度。
2. assert函数的基本语法assert语句的基本语法如下:assert expression [, arguments]•expression:需要进行断言的条件,当该条件为假时,assert语句会抛出AssertionError异常。
•arguments:可选参数,用于传递给AssertionError异常的附加信息,可以是字符串、数字或其它对象。
3. assert函数的使用场景assert函数一般用于以下几种场景:3.1. 检查前置条件在编写函数或方法时,我们经常需要检查输入参数是否满足一定的前置条件。
使用assert函数可以简化检查的逻辑,例如:def divide(x, y):assert y != 0, "除数不能为零"return x / y在这个例子中,assert语句用于检查除数是否为零,如果为零则抛出AssertionError异常并提示“除数不能为零”。
3.2. 检查后置条件对于一些需要满足一定条件的返回值,我们可以使用assert函数来检查后置条件。
例如:def get_positive_number():x = int(input("请输入一个正整数:"))assert x > 0, "输入必须为正整数"return x在这个例子中,assert语句用于检查用户输入的是否为正整数,如果不是则抛出AssertionError异常并提示“输入必须为正整数”。
3.3. 检查循环不变量在循环中,我们可以使用assert函数来检查循环不变量是否满足预期。
Delphi异常处理tryexcept语句和tryfin(精)

一、异常的来源在Delphi的应用程序中,下列的情况都比较有可能产生异常。
(1)文件处理(2)内存分配(3)Windows 资源(4)运行时创建对象和窗体(5)硬件和操作系统冲突二、异常的处理(1)try…except…end;在try体内的代码发生异常时,系统将转向except部分进行异常的处理。
这是Delphi处理异常的最基本的方式之一。
(2)try…finally…end;这种异常处理结构一般用于保护Windows的资源分配等方面,它确保了无论try体内的代码是否发生异常,都需要由系统进行最后的统一处理的一些Windows对象的正确处理。
和try…except…end不同,该结构的finally部分总被执行。
(3)不存在try…except…finally…end结构来既处理异常,又保护资源分配的结构,但是,try…except…end结构允许嵌套到try…finally…end结构中,从而实现既处理异常,又保护资源的分配。
三、异常的精确处理(1)定义一个异常。
在Delphi中,每个异常都是Exception[1]类的一个派生类[2]。
因此,定义一个异常就是定义一个Exception类的派生类。
type EMyException =class(Exception;当然,基类可以是Exception或者Exception的任何一个任何层次的派生类。
(2)在程序中抛出一个异常。
根据不同的情况抛出异常是使用异常的最基本的模式。
在Delphi中,由raise语句来实现。
【语法】raise 异常类.Create(…异常的缺省说明‟; (3)在try…except…end 中更加精确的捕捉异常。
使用on E:异常类do…结构可以在do体内处理特定异常类所抛出的异常。
四、异常的调试在Delphi IDE中,解除“Debugger Options”(可以使用菜单Tools—>Debugger Options…进行访问)中的Integrated Debugging复选框的勾选状态可以进行异常的调试。
delphi异常和错误处理

异常和错误处理(基于Delphi/VCL)有人在看了我的“如何将界面代码和功能代码分离(基于Delphi/VCL)”之后,提到一个问题,就是如何对服务端的类的错误进行处理。
在基于函数的结构中,我们一般使用函数返回值来标明函数是否成功执行,并给出错误类型等信息。
于是就会有如下形式的代码:RetVal := SomeFunctionToOpenFile();if RetVal = E_SUCCESSED then......else if RetVal = E_FILENOTFOUND then......else if RetVal = E_FILEFORMATERR then......else then......使用返回错误代码的方法是非常普遍的,但是使用这样的方法存在2个问题:1、造成冗长、繁杂的分支结构(大量的if或case语句),使得控制流程变得复杂2、可能会有没有被处理的错误(函数调用者如果不判断返回值的话)而异常是对于错误处理的面向对象的解决方案。
它可以报告错误,但需要知道的是,并非由于错误而引发了异常,而仅仅是因为使用了raise。
在Object Pascal中,抛出异常使用的是raise保留字。
在任何时候(即使没有错误发生),raise都将会导致异常的发生。
异常可以使得代码从异常发生处立刻返回,从而保护其下面的敏感代码不会得到执行。
通过异常从函数返回和正常从函数返回(执行到函数末尾或执行了Exit)对于抛出异常的函数本身来说是没有什么区别的。
区别在于调用者处,通过异常返回后,执行权会被调用者的try...e xcept块所捕获(如果它们存在的话)。
如果调用者处没有try...except块的话,将不会继续执行后续语句,而是返回更上层的调用者,直至找到能够处理该异常的try...except块。
异常被处理后,将继续执行try...except块之后的语句,控制权就被留在了处理异常的这一层。
delphi调试技巧

delphi调试技巧Delphi开发的调试技巧1、设置调试选项Delphi主菜单。
【Project】->【Options】,或单击工程管理器中的【Project Options】按钮。
显示Project Options,选择Complier<1>选中 Debug Information :把调试信息嵌入到DCU单元文件,会加大编译后的DCU文件,但不会影响最后生成的exe的大小和执行速度。
同时激活【Search】菜单中的【Find Error】命令。
当文件中包含调试信息并得到一个运行时错误(run-time error),记录下Delphi提供的16进制地址,在【Search】->【Find Error】中输入,Delphi将重新编译程序,并停留在产生错误的命令行。
<2>Local symbols:决定调试器能否看到在Implementation中定义的局部变量。
<3>Reference infoj选项/Definition Only选项是否产生应用程序中对象标识符的引用信息。
信息和对象代码存在dcu文件中,可以使用对象浏览器查看。
如果Definition Only 选项同时选中,编译器将生成标识符定义位置的信息,能够激活对象浏览器的Refenrence页。
如果不选,Dcu文件更小。
编辑器命令{$D} Debug Information{$L} Local Information{$Y} Symbol Information{$C} Assertions2、使用内部调试器<1> 命令行参数在【Run】->【Parameters】中设置<2>断点条件断点使源代码断点只有在满足某个条件时才有效。
在【View】->[Debug windows]->【BreakPoints】打开“BreakPoint List”对话框,右击断点,从弹出菜单中选择属性。
delphi异常和错误处理

异常和错误处理(基于Delphi/VCL)有人在看了我的“如何将界面代码和功能代码分离(基于Delphi/VCL)”之后,提到一个问题,就是如何对服务端的类的错误进行处理。
在基于函数的结构中,我们一般使用函数返回值来标明函数是否成功执行,并给出错误类型等信息。
于是就会有如下形式的代码:RetVal := SomeFunctionToOpenFile();if RetVal = E_SUCCESSED then......else if RetVal = E_FILENOTFOUND then......else if RetVal = E_FILEFORMATERR then......else then......使用返回错误代码的方法是非常普遍的,但是使用这样的方法存在2个问题:1、造成冗长、繁杂的分支结构(大量的if或case语句),使得控制流程变得复杂2、可能会有没有被处理的错误(函数调用者如果不判断返回值的话)而异常是对于错误处理的面向对象的解决方案。
它可以报告错误,但需要知道的是,并非由于错误而引发了异常,而仅仅是因为使用了raise。
在Object Pascal中,抛出异常使用的是raise保留字。
在任何时候(即使没有错误发生),raise都将会导致异常的发生。
异常可以使得代码从异常发生处立刻返回,从而保护其下面的敏感代码不会得到执行。
通过异常从函数返回和正常从函数返回(执行到函数末尾或执行了Exit)对于抛出异常的函数本身来说是没有什么区别的。
区别在于调用者处,通过异常返回后,执行权会被调用者的try...e xcept块所捕获(如果它们存在的话)。
如果调用者处没有try...except块的话,将不会继续执行后续语句,而是返回更上层的调用者,直至找到能够处理该异常的try...except块。
异常被处理后,将继续执行try...except块之后的语句,控制权就被留在了处理异常的这一层。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
delphi 下用assert 来完成错误的捕捉
delphi 下用assert 来完成错误的捕捉
Assert 过程原形procedure Assert (expr :Boolean [; const msg: string]);在system.pas 里Assert 的实现是:
procedure _Assert(const Message, Filename: AnsiString; LineNumber: Integer);
{$IFDEF PUREPASCAL}
begin
if Assigned(AssertErrorProc) then
AssertErrorProc(Message, Filename, LineNumber, Pointer(-1)) else
Error(reAssertionFailed);
// loses return addressend;
{$ELSE}
asm PUSH EBX
{$IFDEF PIC}
PUSH EAX
PUSH ECX
CALL GetGOT
MOV EBX, EAX
MOV EAX, [EBX].
AssertErrorProc
CMP [EAX], 0
POP ECX POP EAX
{$ELSE}
CMP AssertErrorProc,0{$ENDIF} JNZ @@1
MOV AL,reAssertionFailed
CALL Error
JMP @@exit
@@1: PUSH [ESP+4].Pointer
{$IFDEF PIC}
MOV EBX, [EBX].AssertErrorProc
CALL [EBX]
{$ELSE}
CALL AssertErrorProc
{$ENDIF}
@@exit: POP EBX
end;
{$ENDIF}
可以看出AssertErrorProc() 是没有初值的,通过对其赋值可以定义自己的Assert处理过程,
另如果未对AssertErrorProc赋值,将调用Error()处理过程来做为异常处理.
TAssertErrorProc = procedure (const Message, Filename: string; LineNumber: Integer; ErrorAddr: Pointer);
{$ASSERTIONS OFF/ON} 开关来决定Assert是否被调用. 可以在project-option-complier里设置.
这样就可以在beta或debug版本是打开,而最终发布时关闭调试输出了.
一个简单的AssertErrorProc 例程:
unit AssertLogs;
interface
implementation
uses
Windows,
SysUtils;
var
runErrMsg : String;
oldAssertErrorProc : TAssertErrorProc;
procedure LogAssert(const Message, Filename: string; LineNumber: Integer; ErrorAddr: Pointer);
begin
runErrMsg := format('Error: %s, Addr: %p, in file(%d): %s ', [Message, ErrorAddr, LineNumber, FileName]);
if IsConsole then
Writeln(runErrMsg)
else
MessageBox(0, pChar(runErrMsg), 'Error Log by AssertLogs', 0);
end;
initialization
oldAssertErrorProc := AssertErrorProc;
AssertErrorProc := @LogAssert;
finalization
AssertErrorProc := oldAssertErrorProc;
end.
************************************* 那么在output debug信息时只需要: Assert(false,outputstring);。