В C я использовал цепочки goto для освобождения ресурсов при ошибке, как рекомендовано здесь .Работая с Delphi, я столкнулся со следующей ситуацией, когда я хочу изящно обработать исчерпание памяти, а также предотвратить утечки памяти:
New(A);
A.DoSomething;
New(A.B);
A.B.DoSomething;
New(A.C);
A.C.DoSomething;
Как я понимаю, способ проверки исчерпания памяти заключается в перехвате исключенияна 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;
Перехват исключений на вызывающем абоненте:
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
казалось хуже, и это было все, о чем я мог думать до сих пор.