【发布时间】:2018-11-05 07:39:22
【问题描述】:
在 C 中,我使用 goto 链在出错时释放资源,推荐 here。在使用 Delphi 时,我遇到了以下情况,我想优雅地处理内存耗尽并防止内存泄漏:
New(A);
A.DoSomething;
New(A.B);
A.B.DoSomething;
New(A.C);
A.C.DoSomething;
据我了解,检查内存耗尽的方法是捕获New 引发的异常。假设DoSomething 函数都在错误时抛出Exception。 SEI CERT 的编码标准建议反对in-band error checking 和反对using exceptions for control flow,至少对于Java,我觉得这很合理。我不确定如何处理这种情况,牢记这些建议。我的想法是做类似的事情
function AllocStuff : TA;
begin
New(Result);
Result.B := nil;
Result.C := nil;
Result.DoSomething;
New(Result.B);
Result.B.DoSomething;
New(Result.C);
Result.C.DoSomething;
end;
在调用者上捕获异常:
procedure QuestionableControlFlow;
var
A : TA;
begin
A := nil;
try
A := AllocStuff;
DoSomethingWith(A);
Dispose(A);
except on E : Exception do
begin
if (A <> nil) then
begin
if (A.B <> nil) then
begin
if (A.C <> nil) then
begin
Dispose(A.C);
end;
Dispose(A.B);
end;
Dispose(A);
end;
end;
end;
这真的像看起来那么糟糕吗?将goto 与except 混合在一起似乎更糟,到目前为止我能想到的只有这些。
【问题讨论】:
-
goto通常被认为是邪恶的,如果有的话,应该很少使用它。对于 C++,更好的解决方案是改用 RAII,然后在堆栈上创建对象,并让它们的析构函数在对象超出范围时释放资源。不过,C 和 Delphi 没有 RAII 或带有析构函数的基于堆栈的对象。在 Delphi 中,您可以使用接口模拟 RAII。
标签: oop delphi memory-management exception-handling