在Delphi 5中,可以自由生成一个异常



在Delphi 5中,我目前已经编写了在finally块中的多个变量上调用Free的代码,例如

...
finally
    a.Free;
    b.Free;
    c.Free;
end;

此代码假设Free永远不能提升,因为例如,如果a.Free提升,则bc的内存将泄漏。这个假设合理吗?

Free方法本身并没有显式引发异常,但它调用了虚拟析构函数Destroy,这肯定会引发异常。

因此,如果你想确保所有的对象都被销毁了,即使其中一个析构函数引发了异常,你最终也会得到这样的代码:

a := TMyObject.Create;
try
  b := TMyObject.Create;
  try
    ...
  finally
    b.Free;
  end;
finally
  a.Free;
end;

话虽如此,设计原则应该是不要在析构函数中引发异常。因此,在我看来,如果在析构函数中引发了异常,那么你的程序几乎被冲洗掉了,这种观点是完全合理的。在这一点上泄漏物体是不需要担心的。如果你的析构函数引发了一个异常,那么你可能已经在泄漏了,因为析构函数没有运行到完成。

因此,在我看来,将一些对Free的调用组合在一起是完全合理的,当然也可以避免深度嵌套的try/finally,这是值得努力的。

如果你只想要一个try/finally,那么记得这样写代码:

a := nil;
b := nil;
try
  a := TMyObject.Create;
  b := TMyObject.Create;
  ...
finally
  b.Free;
  a.Free;
end;

在我自己的代码库中,我有一些帮助方法可以使它更干净。然后代码可以看起来像这样:

InitialiseNil(a, b);
try
  a := TMyObject.Create;
  b := TMyObject.Create;
  ...
finally
  FreeAndNil(b, a);
end;

我给我的FreeAndNil起了与SysUtils中的函数相同的名字,乍一看可能很奇怪,但这样做是安全和友好的。当你有两个以上的对象时,这些助手自然会有自己的作用。

取决于析构函数中发生的事情。

可能有两件事会导致SomeObj.Free引发异常:

  1. 类或其祖先的SomeObj实例的析构函数中出现未处理的异常
  2. 由于未初始化变量SomeObj,类引用无效

在您的情况下,如果a.Free由于上述任何原因引发异常,则对象bc将发生内存泄漏,并且可能由于析构函数中未处理的异常而导致对象a内部发生一些泄漏。

如果a.free引发异常,a(取决于析构函数从a的对象字段中释放了多少)、b和c对象将被泄漏,因为执行将被中断。不管怎样,如果析构函数引发错误,它就会出错。因此,您应该使用try..来保护代码。。finally阻塞,但是IMHO您应该验证析构函数在任何情况下都不会给您错误。

当然FREE可以发出异常-所以是的,如果A.FREE发出异常,B.FREE和C.FREE将不会被调用,那么你的代码中就会泄漏内存。

问题是,你想处理异常还是让它们发生?这将取决于您的代码将用于什么,其他开发人员是否将使用它(例如)。为了防止任何内存泄漏,您应该嵌套try。。最后是章节;

a:=tobject.create;
try
  b:=tobject.create;
  try
    c:=tobject.create;
    ...
  finally
    c.free;
  end;
finally
  b.free;
end;
a.free;

有点像。这是一个问题,你的代码实际上在做什么,以及你是否也应该在一次尝试中包装a.FREE。。最后一节也是,尽管我猜你可能应该这样做。

相关内容

最新更新