在Delphi 5中,Free可以提出例外吗?

时间:2012-02-08 10:00:06

标签: delphi exception-handling delphi-5

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

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

此代码假定Free永远不会引发,因为例如,如果引发a.Freebc的内存将会泄露。这个假设是否合理?

5 个答案:

答案 0 :(得分:11)

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;

我已将FreeAndNilSysUtils中的函数同名,乍一看似乎很奇怪,但这样做是安全和良性的。当你有两个以上的物体时,这些助手自然会自成一体。

答案 1 :(得分:3)

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

答案 2 :(得分:2)

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

  1. SomeObj类实例或其祖先的析构函数中的未处理异常。
  2. 由于未初始化的变量SomeObj而导致无效的类引用。
  3. 如果由于上述任何原因导致a.Free引发异常,则对象bc会出现内存泄漏,并且对象内部可能会发生泄漏{{1因为析构函数中的未处理异常。

答案 3 :(得分:1)

如果你的a.free引发异常,a(取决于析构函数从a的对象字段中释放了多少),b和c对象将会泄漏,因为执行将被中断。无论如何,如果它引发错误,你的析构函数就会出错。所以,你应该使用try..finally块保护代码,但恕我直言,你应该验证析构函数在任何情况下都不会给你错误。

答案 4 :(得分:0)

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

问题是,您想要处理异常还是让它们发生?它取决于你的代码将用于什么,其他开发者将使用它(例如)。为了防止任何内存泄漏,你应该嵌套try..finally部分;

a:=tobject.create;
try
  b:=tobject.create;
  try
    c:=tobject.create;

    ...

  finally
    c.free;
  end;
finally
  b.free;
end;
a.free;

有点东西。它是一个关于你的代码实际上在做什么的问题,如果你也应该将A.FREE包装在try..finally部分中,尽管我猜你应该这样做。