Lesson 8 · 8 of 20
Try/finally and cleanup · Pascal
Make sure your objects are released even when errors happen with try/finally in Object Pascal, the pattern that prevents memory leaks.

In Pascal you free objects yourself, and an error halfway through could skip the Free. A `try ... finally` block prevents that: whatever follows finally runs every time, whether the try code finishes normally or raises an exception.
Import follows the classic pattern: it creates the list before the try (if Create failed, there would be nothing to free) and frees it inside finally. In between it converts each text with StrToFloat and adds it to prices.
The first call imports all three prices and prints the total. In the second, StrToFloat('n/a') raises EConvertError after importing 12.00. Look at the order of the output: first Freeing a list of 1, because the finally block runs while the exception is on its way out, and then Import failed, when the main program's try ... except catches it.
finally catches nothing: the exception keeps going, which is why This line is skipped never appears. The two blocks complement each other: `finally` cleans up and `except` decides what to do about the error. In a Lazarus app, every temporary object should be protected like this.
Code · 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.Output · 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
Key points
- Whatever is in
finallyalways runs. - Create the object before the
tryand free it infinally. finallydoes not stop the exception; it only cleans up.exceptdecides what to do;finallydecides what to release.- This is how you avoid memory leaks.
Exercise
Make Import save the valid prices with prices.SaveToFile('prices.txt') just before finally, and check that the second call never gets to write it.