In modern programming, runtime errors (like file not found, division by zero, or invalid data) should not crash the application. Exception Handling allows the program to gracefully catch these errors, recover, and continue running.
1. The Exception Model
An Exception is an object that represents an unexpected event or error that has occurred during program execution.
- Raising: When an error occurs, the system or a developer’s code raises (or throws) an exception object.
- Handling: The program must use a
try...exceptblock to catch (handle) the exception. If an exception is raised and not caught, the program terminates.
2. The try...except Block (Error Trapping)
The try...except structure allows you to execute a block of code and define specific routines to handle any exceptions that might occur within that block.
try
// 1. Monitored Code Block: Code where an exception might occur
Writeln('Starting calculation...');
Result := Numerator / Denominator; // Potential EDivByZero exception here
Writeln('Calculation complete.');
except
// 2. Exception Handling Block: Code that runs if an exception is raised
// Catch ALL exceptions (general handler)
on E: Exception do
begin
Writeln('An unexpected error occurred.');
Writeln('Error details: ', E.Message);
end;
end;
// Execution continues here after the exception is handled
A. Handling Specific Exceptions
You can catch specific types of exceptions, allowing you to react differently to various errors. All standard exceptions (like EZeroDivide and EFileNotFound) inherit from the base class Exception (which itself inherits from TObject).
uses
SysUtils; // Contains standard exception classes
try
// Attempt to read a number from user input
Value := StrToInt(InputString);
except
// Handle a specific exception first
on EConvertError do
Writeln('Error: Input was not a valid number (conversion error).');
// Handle a different specific exception
on EOverflow do
Writeln('Error: The number was too large for an Integer.');
// Handle all OTHER exceptions (general catch-all)
on E: Exception do
Writeln('A different unexpected error: ', E.Message);
end;
Order Matters: Exception handlers are evaluated in order. Always put the most specific exception handlers first (e.g.,
on EConvertError) and the general handler (on E: Exception) last.
3. The try...finally Block (Guaranteed Cleanup)
The try...finally block is used to guarantee that a section of cleanup code runs, regardless of whether an exception occurred or if the try block completed normally. It does not catch or handle the error; it ensures resource release.
- Crucial Use: This is mandatory for freeing objects allocated on the Heap (P2.4).
var
MyClient: TClient; // Assume TClient is a class
begin
MyClient := TClient.Create('Temp'); // Resource allocated
try
// Main processing code
MyClient.ProcessData;
// If an exception is raised here, the program jumps immediately to finally
finally
// This code ALWAYS runs before the procedure exits
MyClient.Free; // Guarantees the memory is released (no memory leak)
end;
end;
4. Combining Blocks
You can combine both structures for the best reliability: try...except handles the logic of the error, and try...finally handles the memory cleanup.
try // Start the cleanup guarantee
MyStream := TFileStream.Create('data.bin', fmOpenRead); // Resource allocated
try // Start the error trapping
MyStream.Read(Buffer, Size);
except // Handle errors during read operation
on E: Exception do
Writeln('Failed to read file: ', E.Message);
end; // End of error trapping
finally // End of cleanup guarantee
MyStream.Free; // File handle and memory freed, regardless of read status
end;
5. Raising Custom Exceptions
You can create your own exception classes by inheriting from the base Exception class. This allows you to raise meaningful errors specific to your application logic.
type
// Custom exception for when user input is invalid
EInvalidInput = class(Exception);
procedure CheckData(Value: Integer);
begin
if (Value < 0) or (Value > 100) then
begin
// Raise the custom exception object
raise EInvalidInput.Create('Value must be between 0 and 100.');
end;
end;
