Поиск…


Синтаксис

  1. Try-except: try [statements] кроме [[[на E: ExceptionType do statement]] [else statement] | [заявления];

    Try-finally: попробуйте [statements] finally [statements] end;

Простой пример. Наконец, чтобы избежать утечек памяти

Используйте try - finally чтобы избежать утечки ресурсов (например, памяти) в случае возникновения исключения во время выполнения.

Следующая процедура сохраняет строку в файле и предотвращает утечку TStringList .

procedure SaveStringToFile(const aFilename: TFilename; const aString: string);
var
  SL: TStringList;
begin
  SL := TStringList.Create; // call outside the try 
  try
    SL.Text := aString;
    SL.SaveToFile(aFilename);
  finally
    SL.Free // will be called no matter what happens above
  end;
end;

Независимо от того, возникает ли исключение при сохранении файла, SL будет освобожден. Любое исключение отправляется вызывающему абоненту.

Исключительно безопасный возврат нового объекта

Когда функция возвращает объект (вместо того, чтобы использовать тот, который был передан вызывающим), будьте осторожны, исключение не вызывает утечку объекта.

function MakeStrings: TStrings;
begin
  // Create a new object before entering the try-block.
  Result := TStringList.Create;
  try
    // Execute code that uses the new object and prepares it for the caller.
    Result.Add('One');
    MightThrow;
  except
    // If execution reaches this point, then an exception has occurred. We cannot
    // know how to handle all possible exceptions, so we merely clean up the resources
    // allocated by this function and then re-raise the exception so the caller can
    // choose what to do with it.
    Result.Free;
    raise;
  end;
  // If execution reaches this point, then no exception has occurred, so the
  // function will return Result normally.
end;

Наивные программисты могут попытаться поймать все типы исключений и вернуть nil от такой функции, но это всего лишь частный случай общей непривлекательной практики ловли всех типов исключений без их обработки.

Try-finally, вложенный внутри try-except

Блок try finally может быть вложен внутри блока try except .

try
  AcquireResources;
  try
    UseResource;
  finally
    ReleaseResource;
  end;
except
  on E: EResourceUsageError do begin
    HandleResourceErrors;
  end;
end;

Если в UseResource возникает UseResource , выполнение переходит к ReleaseResource . Если исключением является EResourceUsageError , то выполнение перейдет к обработчику исключений и вызовет HandleResourceErrors . Исключения любого другого типа пропустят обработчик исключений выше и перейдут к следующей try - except блокировки стека вызовов.

Исключения в AcquireResource или ReleaseResource заставят выполнение перейти к обработчику исключений, пропуская блок finally , либо потому, что соответствующий блок try еще не введен, либо потому, что блок finally уже введен.

Попробовать - кроме вложенного внутри try-finally

Блок try except может быть вложен в блок try finally .

AcquireResource;
try
  UseResource1;
  try
    UseResource2;
  except
    on E: EResourceUsageError do begin
      HandleResourceErrors;
    end;
  end;
  UseResource3;
finally
  ReleaseResource;
end;

Если в EResourceUsageError появляется UseResource2 , то выполнение перейдет к обработчику исключений и вызовет HandleResourceError . Исключение будет считаться обработанным, поэтому выполнение продолжит UseResource3 , а затем ReleaseResource .

Если в UseResource2 возникает исключение любого другого типа, то обработчик исключений здесь не будет применяться, поэтому выполнение перепрыгнет через вызов UseResource3 и перейдет непосредственно к блоку finally , где будет вызываться ReleaseResource . После этого выполнение перейдет к следующему применимому обработчику исключений, поскольку исключение пузырится вверх по стеке вызовов.

Если исключение возникает в любом другом вызове в приведенном выше примере, тогда HandleResourceErrors не будет вызываться. Это связано с тем, что ни один из других вызовов не возникает внутри блока try соответствующего этому обработчику исключений.

Попробуйте, наконец, с двумя или более объектами

Object1 := nil;
Object2 := nil;
try
  Object1 := TMyObject.Create;
  Object2 := TMyObject.Create;
finally
  Object1.Free;
  Object2.Free;
end;

Если вы не инициализируете объекты с помощью nil вне блока try-finally , если один из них не может быть создан, AV будет происходить в блоке finally, потому что объект не будет равен nil (поскольку он не был инициализирован) и приведет к исключению.

Метод Free проверяет, равен ли объект нулю, поэтому инициализация обоих объектов с помощью nil позволяет избежать ошибок при их освобождении, если они не были созданы.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow