Delphi异常处理 - 如何正确清理? [英] Delphi Exception Handling - How to clean up properly?

查看:168
本文介绍了Delphi异常处理 - 如何正确清理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在查看我们应用程序中的一些代码,并发现我通常做的一些奇怪的事情。使用异常处理和清理,我们(以及许多其他程序员,我确定)使用嵌入Try / Except块的Try / Finally块。现在我习惯了Try / Even里面的Try / Finally,如下所示:

 尝试
尝试
CouldCauseError(X);
除了
HandleError;
结束
最后
FreeAndNil(x);
结束

但这个其他代码块是相反的:

 尝试
尝试
CouldCauseError(X);
最后
FreeAndNil(x);
结束
除了
HandleError;
结束

环顾四周,我看到两个人都这样做,没有解释为什么。我的问题是,哪个获取外部块,哪个获取内部块?或者,除了最后的部分,无论其结构如何,都会被处理。谢谢。

解决方案

一个区别是try..finally..except可能容易受到异常屏蔽情况的影响。 >

想象一下,在 CouldCauseError()中发生异常。然后假设在最终 FreeAndNIL (X)的尝试导致另外的异常。原来的异常(很可能导致导致 FreeAndNIL ()异常)的不稳定性丢失。 除了处理程序,现在正在处理在原始版本之后发生的下游异常。



try..except..finally 当然可以避免这种情况,因此,应该优先考虑(尽可能接近异常处理)。



另一种处理简单的方法例外情况(正在清理的单个对象)将在异常处理程序中的正常流程 中包含清理:

  try 
CouldCauseError(X);
FreeAndNil(x);
除了
HandleError;
FreeAndNil(x);
结束

这看起来有点吓人(我需要确定 FreeAndNIL (X)被调用,所以我有一个 FINALLY !!),但是第一个FreeAndNIL()可能不被调用的唯一方法是如果有一个异常, em>是一个例外,你是FreeAndNIL(),以及反过来,它使得清除的顺序在异常情况下更清晰一些(在某种程度上消除噪音的意义是过滤,以了解发生了什么)。



但是,我个人不喜欢 - 如果您更改异常处理程序或正常流程中的代码您有风险打破清理行为,但是根据这个块的代码以及块本身的大小,为了简化起见,在某些情况下,可以认为噪声的减少是合理的。



然而,这依赖于 FreeAndNIL ()实际上 NILThenFree ()... X 在Free'd之前没有,所以如果 FreeAndNIL 发生异常X)在正常流程中,则当异常处理程序捕获由 X.Free 引发的异常时,X将为NIL,因此它不会尝试双重释放X。



无论你决定什么,我希望有帮助。


I'm looking at some code in an application of ours and came across something a little odd from what I normally do. With exception handling and cleanup, we (as well as many other programmers out there, I'm sure) use a Try/Finally block embedded with a Try/Except block. Now I'm used to the Try/Except inside the Try/Finally like so:

Try
  Try
    CouldCauseError(X);
  Except
    HandleError;
  end;
Finally
  FreeAndNil(x);
end;

but this other block of code is reversed as so:

Try
  Try
    CouldCauseError(X);
  Finally
    FreeAndNil(x);
  end;
Except
  HandleError;
end;

Looking around the web, I'm seeing folks doing this both ways, with no explanation as to why. My question is, does it matter which gets the outside block and which gets the inside block? Or will the except and finally sections get handled no matter which way it is structured? Thanks.

解决方案

One difference is that try..finally..except is potentially vulnerable to an exception masking situation.

Imagine that an exception occurs in CouldCauseError(). Then imagine that the attempt to FreeAndNIL(X) in the finally causes a further exception. The original exception (quite possibly which lead to the instability leading to the FreeAndNIL() exception) is lost. The except handler is now handling the "downstream" exception that occured after the original one.

try..except..finally avoids this of course and should be preferred for this reason (deal with exceptions as close as possible to their source).

The other way to handle a simple case such as this (a single object being cleaned) is to include the cleanup both in the normal flow and in the exception handler:

try
  CouldCauseError(X);
  FreeAndNil(x);
except
  HandleError;
  FreeAndNil(x);
end;

This looks a little scary at first ("I need to be SURE that FreeAndNIL(X) is called, so I HAVE TO HAVE A FINALLY!!") but the only way that the first FreeAndNIL() might not be called is if there is an exception and if there is an exception you are FreeAndNIL()ing as well anyway, and it makes the order of cleanup in the event of an exception a little clearer (in the sense of removing noise that to some extent has to be "filtered" out in order to understand what is going on).

But, I personally do not like it - if you change code in either the exception handler or the normal flow you risk breaking the cleanup behaviour, but depending on the code around such a block, and the size of the block itself, the reduction in "noise" can be argued to be justified in some cases, for the sake of simplification.

However, this relies on the fact that FreeAndNIL() is actually "NILThenFree()"... X is NIL'd before it is Free'd, so if an exception occurs in the FreeAndNIL(X) in the normal flow, then X will be NIL when the exception handler catches the exception raised by X.Free, so it will not attempt to "double-free" X.

Whatever you decide, I hope that helps.

这篇关于Delphi异常处理 - 如何正确清理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆