Lección 8 · 8 de 20
Try/finally y liberar recursos · Pascal
Garantice que sus objetos se liberan aunque haya errores con try/finally en Object Pascal, el patrón que evita fugas de memoria.

En Pascal los objetos se liberan a mano, y un error a mitad de camino podría saltarse el Free. El bloque `try ... finally` lo impide: lo que va tras finally se ejecuta siempre, tanto si el código de try termina bien como si lanza una excepción.
Import sigue el patrón clásico: crea la lista antes del try (si Create fallara, no habría nada que liberar) y la libera dentro de finally. Entre medias convierte cada texto con StrToFloat y lo añade a prices.
La primera llamada importa los tres precios y escribe el total. En la segunda, StrToFloat('n/a') lanza EConvertError tras importar 12.00. Fíjese en el orden de la salida: primero Freeing a list of 1, porque el finally se ejecuta mientras la excepción sale, y después Import failed, cuando la captura el try ... except del programa principal.
finally no captura nada: la excepción sigue su camino y por eso This line is skipped nunca aparece. Los dos bloques se complementan: `finally` limpia y `except` decide qué hacer con el error. En una aplicación de Lazarus, todo objeto temporal debería ir protegido así.
Código · main.pas
program main;uses SysUtils, Classes;procedure Import(const rows: array of String);var prices: TStringList; row: String; total: Double;begin prices := TStringList.Create; try total := 0; for row in rows do begin total := total + StrToFloat(row); // may raise EConvertError prices.Add(row); end; WriteLn('Imported ', prices.Count, ' prices, total ', total:0:2); finally WriteLn('Freeing a list of ', prices.Count); prices.Free; // runs with or without an error end;end;begin Import(['9.95', '24.50', '3.20']); try Import(['12.00', 'n/a', '7.40']); WriteLn('This line is skipped'); except on E: Exception do WriteLn('Import failed: ', E.Message); end;end.Salida · fpc main.pas && ./main
Imported 3 prices, total 37.65 Freeing a list of 3 Freeing a list of 1 Import failed: "n/a" is an invalid float
Para recordar
- Lo que hay en
finallyse ejecuta siempre. - Cree el objeto antes del
tryy libérelo enfinally. finallyno detiene la excepción; solo limpia.exceptdecide qué hacer con el error;finally, qué liberar.- Así se evitan las fugas de memoria.
Ejercicio
Haga que Import guarde los precios válidos en un fichero con prices.SaveToFile('prices.txt') justo antes del finally, y compruebe que en la segunda llamada no llega a escribirse.