Embarcadero Delphi
Uso de try, except, y finalmente.
Buscar..
Sintaxis
Try-except: try [sentencias] excepto [[[en E: ExceptionType do statement]] [else statement] | [declaraciones] terminan;
Trate-finalmente: intente [sentencias] finalmente [sentencias] final;
Simple intento ... finalmente ejemplo para evitar pérdidas de memoria
Utilice try
- finally
para evitar pérdidas de recursos (como la memoria) en caso de que ocurra una excepción durante la ejecución.
El siguiente procedimiento guarda una cadena en un archivo y evita que la TStringList
fugas.
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;
Independientemente de si se produce una excepción al guardar el archivo, SL
se liberará. Cualquier excepción irá a la persona que llama.
Devolución segura de excepciones de un nuevo objeto.
Cuando una función devuelve un objeto (en lugar de usar uno que ha pasado la persona que llama), tenga cuidado de que una excepción no provoque la fuga del objeto.
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;
Los programadores ingenuos pueden intentar capturar todos los tipos de excepción y devolver nil
partir de esa función, pero eso es solo un caso especial de la práctica general desalentada de capturar todos los tipos de excepción sin manejarlos.
Try-finalmente anidado dentro de try-except
Un bloque try
- finally
puede estar anidado dentro de un try
- except
bloque.
try
AcquireResources;
try
UseResource;
finally
ReleaseResource;
end;
except
on E: EResourceUsageError do begin
HandleResourceErrors;
end;
end;
Si ocurre una excepción dentro de UseResource
, la ejecución saltará a ReleaseResource
. Si la excepción es un EResourceUsageError
, la ejecución saltará al controlador de excepciones y llamará a HandleResourceErrors
. Las excepciones de cualquier otro tipo omitirán el controlador de excepciones de arriba y aumentarán hasta el siguiente try
, except
bloquee la pila de llamadas.
Las excepciones en AcquireResource
o ReleaseResource
harán que la ejecución vaya al controlador de excepciones, saltándose el bloque finally
, ya sea porque el bloque try
correspondiente aún no se ha ingresado o porque el bloque finally
ya se ha ingresado.
Prueba-excepto anidado dentro de prueba-finalmente
Un bloque try
- except
que puede estar anidado dentro de un bloque try
- finally
.
AcquireResource;
try
UseResource1;
try
UseResource2;
except
on E: EResourceUsageError do begin
HandleResourceErrors;
end;
end;
UseResource3;
finally
ReleaseResource;
end;
Si se produce un EResourceUsageError
en UseResource2
, la ejecución saltará al controlador de excepciones y llamará a HandleResourceError
. La excepción se considerará manejada, por lo que la ejecución continuará UseResource3
y luego ReleaseResource
.
Si ocurre una excepción de cualquier otro tipo en UseResource2
, entonces el controlador de excepciones que se muestra aquí no se aplicará, por lo que la ejecución saltará sobre la llamada UseResource3
e irá directamente al bloque finally
, donde se ReleaseResource
. Después de eso, la ejecución saltará al siguiente controlador de excepción aplicable, ya que la excepción aumenta la pila de llamadas.
Si se produce una excepción en cualquier otra llamada en el ejemplo anterior, no se llamará a HandleResourceErrors
. Esto se debe a que ninguna de las otras llamadas se produce dentro del bloque try
correspondiente a ese controlador de excepciones.
Probar-finalmente con 2 o más objetos.
Object1 := nil;
Object2 := nil;
try
Object1 := TMyObject.Create;
Object2 := TMyObject.Create;
finally
Object1.Free;
Object2.Free;
end;
Si no inicializa los objetos con nil
fuera del bloque try-finally
, si uno de ellos no se crea, se producirá un AV en el bloque finally, porque el objeto no será nulo (ya que no se inicializó) y causará una excepción
El método Free
comprueba si el objeto es nulo, por lo que al inicializar ambos objetos con nil
evitan errores al liberarlos si no se crearon.