用于goto链的OOP等效于在出错时释放资源?

afa*_*rah 2 delphi oop memory-management exception-handling

在C我使用转到链条在错误释放资源,建议在这里.使用Delphi我遇到了以下情况,我想优雅地处理内存耗尽并防止内存泄漏:

New(A);
A.DoSomething;
New(A.B);
A.B.DoSomething;
New(A.C);
A.C.DoSomething;
Run Code Online (Sandbox Code Playgroud)

据我所知,检查内存耗尽的方法是捕获由异常引发的异常New.假设DoSomething所有函数都抛出Exception错误.SEI CERT的编码标准建议不要使用带内错误检查,也不要使用控制流的异常,至少对于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;
Run Code Online (Sandbox Code Playgroud)

捕获调用者的异常:

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;
Run Code Online (Sandbox Code Playgroud)

这看起来像它一样糟糕吗?混合goto使用except似乎更糟糕,这是我所能想到的那么远.

Dav*_*nan 7

在Delphi中,您可以使用try/finally非托管资源生命周期.

例如

obj := TObject.Create;
try
  obj.DoSomething;
finally
  obj.Free;
end;
Run Code Online (Sandbox Code Playgroud)

你绝对不会使用try/except它,虽然这是一个常见的错误.这是为了处理与保证最终确定不同的异常.

当您需要在一个函数中处理多个非托管资源时,您可以嵌套try/finally块.当筑巢很深,可能会很乱.处理这个问题的一些想法可以在这里找到:避免在Delphi中嵌套try ... finally块