Ricerca…


Sintassi

  1. Prova-eccetto: prova [istruzioni] tranne [[[su E: ExceptionType do statement]] [else statement] | [dichiarazioni] fine;

    Try-finally: prova [statement] finally [statement] end;

Prova semplice .. esempio finale per evitare perdite di memoria

Utilizzare try - finally per evitare perdite di risorse (come la memoria) nel caso in cui si verifichi un'eccezione durante l'esecuzione.

La procedura seguente salva una stringa in un file e impedisce a TStringList di fuoriuscire.

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;

Indipendentemente dal fatto che si verifichi un'eccezione durante il salvataggio del file, SL verrà liberata. Qualsiasi eccezione andrà al chiamante.

Ritorno sicuro di un nuovo oggetto

Quando una funzione restituisce un oggetto (invece di usarne uno che è passato dal chiamante), fai attenzione che un'eccezione non provochi la perdita dell'oggetto.

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;

I programmatori ingenui potrebbero tentare di catturare tutti i tipi di eccezione e restituire nil da tale funzione, ma questo è solo un caso speciale della pratica scoraggiata generale di catturare tutti i tipi di eccezione senza gestirli.

Prova finalmente nidificata dentro prova - eccetto

Un blocco try - finally può essere annidato all'interno di un try - except blocco.

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

Se si verifica un'eccezione all'interno di UseResource , l'esecuzione passerà a ReleaseResource . Se l'eccezione è EResourceUsageError , l'esecuzione salterà al gestore delle eccezioni e chiamerà HandleResourceErrors . Eccezioni di qualsiasi altro tipo salteranno il gestore di eccezioni sopra e salveranno al prossimo try - except blocco dello stack di chiamate.

Le eccezioni in AcquireResource o ReleaseResource causeranno l'esecuzione al gestore delle eccezioni, saltando il blocco finally , perché il blocco try corrispondente non è ancora stato immesso o perché il blocco finally è già stato immesso.

Prova - eccetto nidificata dentro prova-finalmente

Un try - except blocco può essere annidato all'interno di un blocco try - finally .

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

Se si verifica un EResourceUsageError UseResource2 in UseResource2 , l'esecuzione salterà al gestore delle eccezioni e chiamerà HandleResourceError . L'eccezione verrà considerata gestita, quindi l'esecuzione continuerà a UseResource3 e quindi ReleaseResource .

Se un'eccezione di qualsiasi altro tipo si verifica in UseResource2 , lo show del gestore di eccezioni qui non verrà applicato, quindi l'esecuzione salterà sulla chiamata UseResource3 e passerà direttamente al blocco finally , dove verrà chiamato ReleaseResource . Successivamente, l'esecuzione salterà al successivo gestore di eccezioni applicabile mentre l'eccezione riempie lo stack di chiamate.

Se si verifica un'eccezione in qualsiasi altra chiamata nell'esempio precedente, HandleResourceErrors non verrà chiamato. Questo perché nessuna delle altre chiamate si verifica all'interno del blocco try corrispondente a quel gestore di eccezioni.

Prova infine con 2 o più oggetti

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

Se non si inizializzano gli oggetti con nil all'esterno del blocco try-finally , se uno di essi non viene creato verrà eseguito un AV sul blocco finally, poiché l'oggetto non sarà nullo (poiché non è stato inizializzato) e causerà un'eccezione

Il metodo Free verifica se l'oggetto è nullo, quindi l'inizializzazione di entrambi gli oggetti con nil evita errori durante la loro liberazione se non sono stati creati.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow