有一个例子可以说明我的问题:
procedure Test;
begin
try
ShowMessage('1');
raise EWarning.Create(12345, 'Warning: something is happens!');
ShowMessage('2');
except
on E: EWarning do
if IWantToContinue(E.ErrorCode) then
E.SkipThisWarning // shows '1' then '2'
else
E.StopExecution; // shows '1'
end;
end;
function IWantToContinue(const ErrorCode: Integer): Boolean;
begin
//...
end;
字符串
我试着用这样的东西:
asm
jmp ExceptAddr
end;
型
但没用的。
有什么想法吗?
谢谢.
6条答案
按热度按时间hec6srdp1#
不,这是不可能的:
有两种异常:由程序员使用
raise
命令引发的逻辑异常,以及由CPU在各种情况下引发的外部异常:被零除、堆栈溢出、访问冲突。对于第一种,即逻辑异常,您无能为力,因为它们是应用程序“流程”的一部分。您不能打乱第三方代码的流程,您甚至不能打乱自己的代码流。外部异常
当一条指令失败时,这些异常通常是由于运行一条CPU指令而产生的。在 Delphi 中,这些异常作为
EExternal
的后代可用。列表中包括访问冲突、被零除、堆栈溢出、特权指令和其他不多的异常。理论上,对于这些异常中的一些,可以删除引起异常的条件,并重试该条CPU指令。允许原始代码像没有发生错误一样继续运行。2例如,一些访问冲突可能通过在发生错误的地址实际Map一页RAM来“修复”。在SEH中有规定(Structured Exception Handling)机制来处理这种可重试的错误, Delphi 也在使用SEH。不幸的是,Delphi没有公开所需的元素来使其易于访问,因此使用它们将非常困难,如果不是不可能的话。尽管如此,对于特定类型的
EExternal
错误,聪明的Delphinians可能会尝试编写自定义SEH代码并使其正常工作。如果是这种情况,请提出一个新问题,说明您遇到的特定类型的错误以及您要采取的步骤来删 debugging 误条件:您将得到一些工作代码或自定义的解释,说明您的想法为什么不起作用。通过使用
raise
启动的逻辑异常大多数异常都属于这一类,因为大多数代码在执行潜在危险的低级操作之前都会检查其输入。例如,当试图访问
TList
中的无效索引时,在试图访问所请求的索引之前,会检查该索引并引发无效索引异常。如果不进行检查,访问无效索引将返回无效数据或引发访问冲突。这两种情况都很难跟踪错误,因此无效索引异常是一件非常好的事情。为了回答这个问题,即使允许代码访问无效的索引,从而导致访问冲突,也不可能“修复”代码并继续,因为无法猜测正确的索引应该是什么。换句话说,修复“逻辑”异常不起作用,也不应该起作用,而且非常危险。如果引发错误的代码是你的代码,那么你可以简单地将其重组为不引发警告异常。如果不是你的代码,那么继续处理异常福尔斯“非常危险”的范畴(更不用说这在技术上是不可能的)当查看已经编写好的代码时,问问自己:如果
raise Exeption
被ShowMessage
替换,代码的行为会正常吗?答案应该大多是"NO, the code would fail anyway"
。对于非常罕见的、非常错误的第三方代码,在没有好的理由的情况下引发异常,您可以在运行时请求有关修补代码的特定帮助,以“从不”引发异常。以下是一些第三方代码中可能包含的内容:
字符串
很明显,在异常之后继续那个代码是不会让东西“自我修复”的。
协力厂商程式码也可能如下所示:
型
代码将在哪里“继续”?很明显不是
"do usefull stuff"
部分,除非代码是专门这样设计的。当然,这些都是一些简单的例子,只是触及了表面。从技术的Angular 来看,在异常之后“继续”,就像你建议的那样,要比跳转到错误的地址困难得多。方法调用使用堆栈空间来设置局部变量。这些空间是在错误之后“回滚”的过程中释放的。
finally
块被执行,可能在需要的地方释放了资源。跳回原始地址是非常错误的,因为调用代码在堆栈上不再有它所期望的,它的局部变量不再是它们所期望的。如果是您的代码引发了异常
你的代码可以很容易地被修复。使用类似这样的方法:
型
pqwbnv8z2#
不,你必须重新构造你的代码,
字符串
5ssjco0h3#
在C++中,可以使用SEH
__try/__except
块,其__except
表达式的计算结果为EXCEPTION_CONTINUE_EXECUTION
。在 Delphi 中,不可能直接使用SEH,AFAIK。
4ktjp1zp4#
基本上,您的代码无法工作,因为
ExceptAddr
是一个函数,而不是一个变量。因此,您的代码片段更改如下:字符串
tzxcd3kk5#
..你可以嵌套多个try-except,并在每个异常中确定是否继续:
字符串
hs1rzwqc6#
这是我使用的例子。下面的过程将从几个URL下载文件(已经是数据集形式)。问题是http经常有问题,所以需要重试机制来尝试再次下载。在这个例子中我将尝试3次,每次我给给予5秒睡眠。重试3次后比将Break;
CDS是TClientDataset Memo是TMemo mnuDownload是TButton或菜单
字符串