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块之后的语句,控制权就被留在了处理异常的这一层。
Delphi 异常处理 详解
{错误处理代码};
使用异常进行错误处理
结构化异常处理是Delphi语言内建的特性.为我们处理异常提供了方便.处理异常有两方面:
1 异常处理可确保适当地恢复在应用程序中分配或改变的任何资源.
2 结构化异常处理为开发人员提供了一种一致的处理各种类型运行期错误的方式
字符转换/类型转换异常和哑异常
字符转换异常
EConvertError 数字到字符串或字符串到数
字转换错误
类型转换异常
EInvalidCast 类型转换异常
哑异常
EAbort 调用Abort产生,不显示错误提示框
对象异常类
对象异常类是针对非组件对象引发的异常而定义的.
Exception是所有异常类的基类,它并不是以’T'开头,而是以’E'开头,它的派生类也是以’E'开头的.
Exception类定义于SysUtils单元中.
Exception类最常用的方法是Create方法:
Constructor Create(const Msg:string);
Exception.Create(‘我自己创建的异常!’);
EDivByZero 整数除0溢处
EIntOverFlow 整数溢出
ERangeError 整数越界
浮点计算异常
EMathError 浮点计算异常(基类)
EInvalidOp 无效浮点操作指令
Eoverflow 浮点操作上溢
Eunderflow 浮点操作下溢
EZeroDivide 浮点计算除0
ShowMessage(Format('生于%d年', [YearOf(Now) - Age]));
VC错误处理技术学习:断言(ASSERT)
VC错误处理技术学习:断言(ASSERT)VC错误处理技术学习:断言(ASSERT)1.1 基本概念断言是一种让错误在运行时候自我暴露的简单有效实用的技术。
它们帮助你较早较轻易地发现错误,使得整个调试过程效率更高。
断言是布尔调试语句,用来检测在程序正常运行的时候某一个条件的值是否总为真,它能让错误在运行时刻暴露在程序员面前。
使用断言的最大好处在于,能在更解决错误的发源地的地方发现错误。
断言具有以下特征:n 断言是用来发现运行时刻错误的,发现的错误是关于程序实现方面的。
n 断言中的布尔表达式显示的是某个对象或者状态的有效性而不是正确性。
n 断言在条件编译后只存在于调试版本中,而不是发布版本里。
n 断言不能包含程序代码。
n 断言是为了给程序员而不是用户提供信息。
使用断言最根本的好处是自动发现许多运行时产生的错误,但断言不能发现所有错误。
断言检查的是程序的有效性而不是正确性,可通过断言把错误限制在一个有限的范围内。
当断言为假,激活调试器显示出错代码时,通常能检查出导致断言失败的原因。
_ASSERTE宏(属于C运行时间库)还能在断言失败时显示出失效断言。
1.2 C中的断言(assert)assert宏在C语言程序的调试中发挥着重要的作用,它用于检测不会发生的情况,表明一旦发生了这样的情况,程序就实际上执行错误了,例如strcpy函数:char *strcpy(char *strDest, const char *strSrc){char *address = strDest;assert((strDest != NULL) && (strSrc != NULL));while ((*strDest++ = *strSrc++) != ’\0’);return address;}其中包含断言assert( (strDest != NULL) && (strSrc != NULL) ),它的意思是源和目的字符串的地址都不能为空,一旦为空,程序实际上就执行错误了,会引发一个abort。
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. 异常捕获的技术手段为了对错误进行处理,前端开发人员可以利用一些技术手段来捕获异常。
常见的技术手段包括try-catch语句、全局错误事件监听、Promise的catch方法等。
通过这些技术手段,开发人员可以在代码中捕获错误,并采取相应的处理措施,而不会影响整个页面或应用的运行。
3. 错误信息的收集和上报在错误处理的过程中,收集错误信息并进行上报是非常重要的。
通过错误信息的收集和上报,开发人员可以及时了解到出现的错误情况,并进行后续的分析和处理。
为了实现错误信息的收集和上报,可以使用一些前端监控工具,如Sentry、Bugsnag等。
这些工具可以帮助开发人员捕获和分析错误信息,并提供详细的报告和统计数据,以便进行问题定位和修复。
4. 最佳实践和常见问题在进行错误处理和异常捕获时,有一些最佳实践和常见问题需要注意。
首先,正确地使用try-catch语句。
try-catch语句应该尽量精确地包裹可能会出错的代码块,以避免捕获到不相关的错误。
其次,错误信息应该提供足够的详细信息,但避免泄露敏感信息。
错误信息应该清晰明了地描述问题,同时避免暴露敏感数据,如用户的个人信息等。
另外,错误处理还需要考虑用户体验。
通过优化界面和提供友好的提示信息,可以帮助用户更好地理解错误并采取相应的操作。
Flutter里面错误捕获的正确方法
Flutter⾥⾯错误捕获的正确⽅法背景我们知道,在软件开发过程中,错误和异常总是在所难免。
不管是客户端的逻辑错误导致的,还是服务器的数据问题导致的,只要出现了异常,我们都需要⼀个机制来通知我们去处理。
在 APP 的开发过程中,我们通过⼀些第三⽅的平台,⽐如 Fabric、Bugly 等可以实现异常的⽇志上报。
Flutter 也有⼀些第三⽅的平台,⽐如 Sentry 可以实现异常的⽇志上报。
但是为了更加通⽤⼀些,本篇不具体讲解配合某个第三⽅平台的异常⽇志捕获,我们会告知⼤家如何在 Flutter ⾥⾯捕获异常。
⾄于具体的上报途径,不管是上报到⾃家的后台服务器,还是通过第三⽅的 SDK API 接⼝进⾏异常上报,都是可以的。
Demo 初始状态⾸先我们新建 Flutter 项⽬,修改 main.dart 代码如下:import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {// This widget is the root of your application.@overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: Text('Flutter Crash Capture'),),body: MyHomePage(),),);}}class MyHomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Container();}}效果如下:捕获错误我们修改 MyHomePage,添加⼀个 List 然后进⾏越界访问,改动部分代码如下:class MyHomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {List<String> numList = ['1', '2'];print(numList[6]);return Container();}}可以看到控制台报错如下:flutter: ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY╞═══════════════════════════════════════════════════════════flutter: The following RangeError was thrown building MyHomePage(dirty):flutter: RangeError (index): Invalid value: Not in range 0..1, inclusive: 6当然这些错误信息在界⾯上也有显⽰(debug 模式)。
delphi下用assert来完成错误的捕捉
delphi下用assert来完成错误的捕捉delphi 下用assert 来完成错误的捕捉Assert 过程原形1.procedure Assert (expr :Boolean [; const msg: string]);在system.pas 里 Assert 的实现是:procedure _Assert(const Message, Filename: AnsiString; LineNumber: Integer);{$IFDEF PUREPASCAL}beginif Assigned(AssertErrorProc) thenAssertErrorProc(Message, Filename, LineNumber, Pointer(-1)) elseError(reAssertionFailed);// loses return address end;{$ELSE}asm PUSH EBX{$IFDEF PIC}PUSH EAXPUSH ECXCALL GetGOTMOV EBX, EAXMOV EAX, [EBX].AssertErrorProcCMP [EAX], 0POP ECX POP EAX{$ELSE}CMP AssertErrorProc,0{$ENDIF} JNZ @@1MOV AL,reAssertionFailedCALL ErrorJMP @@exit@@1: PUSH [ESP+4].Pointer{$IFDEF PIC}MOV EBX, [EBX].AssertErrorProcCALL [EBX]{$ELSE}CALL AssertErrorProc{$ENDIF}@@exit: POP EBXend;{$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;interfaceimplementation uses Windows, SysUtils;varrunErrMsg : String;oldAssertErrorProc : TAssertErrorProc;procedure LogAssert(const Message, Filename: string; LineNumber: Integer; ErrorAddr: Pointer);beginrunErrMsg := format('Error: %s, Addr: %p, in file(%d): %s ', [Message, ErrorAddr, LineNumber, FileName]);if IsConsole thenWriteln(runErrMsg)elseMessageBox(0, pChar(runErrMsg), 'Error Log by AssertLogs', 0);end;initializationoldAssertErrorProc := AssertErrorProc;AssertErrorProc := @LogAssert;finalizationAssertErrorProc := oldAssertErrorProc;end.************************************* 那么在output debug信息时只需要: Assert(false,outputstring);。
Assertionfailure:(!SetThreadContextfailed)问题的解决办法
Assertionfailure:(!SetThreadContextfailed)问题的解决办法Assertion failure: "(!"SetThreadContext failed")"问题的解决办法2012-02-03 14:33:24 我来说两句收藏我要投稿在编译程序并运行后,Delphi2007会提示以下错误(windows 7 64位运行环境):---------------------------bds.exe - bordbk105N.dll---------------------------Assertion failure: "(!"SetThreadContext failed")"in ..\win32src\thread32.cpp at line 412Continue execution?---------------------------Yes No---------------------------———————华丽的分割线————————-Delphi 2007 或2009 在Windows 7 x64 以及其他x64 系统下,退出IDE 时,调试器会产生一个断言错误。
错误窗口标题为:bds.exe –bordbk120N.dll,内容为:Assertion failure: “(!”SetThreadContext failed”)”in ..\win32src\thread32.cpp at line 434。
解决办法是使用一个非官方的补丁程序进行修复。
补丁程序来源:/blog/index.php/2009/07/delphi-2009-windows-7-64-bit-debugger-crash-workaround/Delphi 2009 / Windows 7 / 64 bit Debugger Crash WorkaroundDelphi 2009 / Windows 7 / 64 bit Debugger Crash WorkaroundYesterday I revisited a nasty problem that occurs on Windows 64bit versions. I ran into that when I upgraded to Windows 7, but it seems it affects older 64bit editions of Windows as well.After installing D2009 on a clean Win7 machine I was happy to see that Windows 7 really is what Vista should have been. It works snappy and has a lot of productivity features. But then when I started compiling and debugging a couple of my existing Delphi applications I experienced Debugger crashes almosteverytime when I terminated an application.Unfortunately no matter if you press “Yes” or “No” on that screen – you have to restart the whole Delphi IDE – which basically makes debugging impossible. In some (actually many) cases you even have to terminate Delphi using Windows TaskManager. I tried all of the compatibility settings Win7 offers, as well as running Delphi as Administrator – but no luck.Some research on Google, QC and RAID showed that similar exceptions were reported with older Delphi versions, but apparently only on 64bit Windows editions. As the message already suggests, the problem appears to be an invalid call to a SetThreadContext API call. Some tests showed that you can easily reproduce this issue once you have more that just a single thread in your Delphi application. As you might know, I am doing quite a lot of Web application server development – which by nature create many threads…I created a RAID entry for that (actually an existing one was updated with detailed reproduction steps –iirc) and joined a discussion thread on that topic to see if others are reporting that too. Because of time constraints I did not revisit that issue over the last couple of weeks, but yesterday when I was talking to Daniel Magin, we together found a solution someone had posted on a German Forum a few weeks ago. The original idea is from an MS TechNet posting though (credits go to a guy called XelaxAx).He posted a workaround that basically disables the check for a possible error returned by SetThreadContext, i.e. the debugger ignores the error and does not crash because of the Assert that checks fro no error returned. As Andreas Hausladen already correctly mentioned, this is really just kind of a weak workaround, because the debugger might misbehave after that and we just do not know why SetThreadContext fails at all. The point is though that with this fix I can work effectively again with D2009 on Win7/64bit and as this error only happens when the debugger is about to shout down anyway, so the danger of unwanted side effects is not too high imho.Be careful! No waranties! I am not responsible for lost files etc.! Back up first!Workaround steps:Close DelphiLocate bordbk120N.dll (C:\Program Files (x86)\CodeGear\RAD Studio\6.0\bin)Make a backup copyCheck step 3Open bordbk120N.dll in a Hex editor (UltraEdit works fine) Search for “01 00 48 74 47 80 3D”Make sure this is found once onlyReplace “74” with “EB”SaveRestart Delphi. Error should be gone.This might work on older Delphi versions as well, but I did not test that yet.Update 1I talked to some CodeGear Q&A guy and he tested their current internal Weaver build under the conditions where D2009 fails. The good news is that the error seems to be gone there –so the next Delphi Version will probably be good. For those who want to get started now: please see Update 2 below.Update 2LordByte sent me his automatic patch tool for Delphi 2007 and Delphi 2009. Just click “Apply patch” and you are done.Get the patcherhere: Delphi_2007_2009_WOW64_Debugger_Fix.zip (169 KB)Note: Provided as is for free. Use at your own risk.摘自冷月宫主的专栏。
Delphi中try…except…end与try…finally…end的应用
Delphi中try…except…end与try…finally…end的应用在Delphi的中,提供了try…except…end和try…finally…end语句。
本人在过去得编程过程中,深刻地体会到,这两个语句的合理使用,可以带来很多好处。
一方面可以使程序结构更加清晰,使得我们不用编写大量的意外情况处理的代码;另一方面使我们可以很容易的编写出十分稳定可靠的程序。
一、我们为什么要使用try意外控制语句?假设我们现在要编写一个程序,在这个程序中需要对一个远程文件进行一系列操作。
先看如下代码:代码1:tryOpenRemoteFile;UpdateRemoteFile;CloseRemoteFile;excepton E: Exception dobeginCloseRemoteFile;ShowErrorMessage;end;end;这段代码中OpenRemoteFile和UpdateRemoteFile都有可能由于各种意外情况导致错误,当错误发生后,错误句柄将被捕获,继而执行on E: Exception do之后的语句。
设想如果Delphi没有提供try语句,那么我们的程序将被写成:代码2:if OpenRemoteFile thenbeginif UpdateRemoteFile thenCloseRemoteFile;elsebeginCloseRemoteFile;ShowErrorMessage;end;endelseShowErrorMessage;不用说,这两段程序谁更“好”,谁更不容易出错。
而且在实际使用中可能需要对远程文件做更复杂的操作。
二、try语句的一些简单应用。
在Delphi编程中常常遇到一些必须互相配对的语句,例如:对象的创建和释放;文件的打开和关闭;TDataSet的打开和关闭……。
如果程序中不能很好的处理这些语句,就导致许多不可预测的现象。
请参考如下代码:代码3:显示一个“关于……”对话框。
- 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);。