Exception Handling
14.1 try..except
try
var N := StrToInt(Edit1.Text);
Result := 100 div N;
except
on E: EConvertError do
ShowMessage('Not a valid number: ' + E.Message);
on E: EDivByZero do
ShowMessage('Cannot divide by zero');
on E: Exception do
begin
LogError(E.ClassName + ': ' + E.Message);
raise; // re-raise the same exception
end;
end;14.2 try..finally (Resource Protection)
Delphi has no combined try..except..finally. Nest them: try try ... except ... end; finally ... end;.
var List := TStringList.Create;
try
List.LoadFromFile('data.txt');
Process(List);
finally
List.Free; // ALWAYS runs: prevents leaks
end;
// Nested for multiple resources
var A := TFileStream.Create('a.bin', fmOpenRead);
try
var B := TFileStream.Create('b.bin', fmCreate);
try
B.CopyFrom(A, 0);
finally
B.Free;
end;
finally
A.Free;
end;14.3 Raising and Custom Exceptions
Exception class names start with E by convention. Inherit from Exception.
Common exceptions: EConvertError, EDivByZero, ERangeError, EIntOverflow, EAccessViolation, EInvalidPointer, EOutOfMemory, EAbort (silent: Abort), EFileNotFoundException, EInOutError, EArgumentException, EInvalidOperation, EListError, EDatabaseError, EFDDBEngineException, ENetHTTPClientException.
type
EInsufficientFunds = class(Exception)
private
FShortfall: Currency;
public
constructor Create(AShortfall: Currency);
property Shortfall: Currency read FShortfall;
end;
constructor EInsufficientFunds.Create(AShortfall: Currency);
begin
inherited CreateFmt('Insufficient funds: short by %m', [AShortfall]);
FShortfall := AShortfall;
end;
procedure TAccount.Withdraw(Amount: Currency);
begin
if Amount <= 0 then
raise EArgumentOutOfRangeException.Create('Amount must be positive');
if Amount > FBalance then
raise EInsufficientFunds.Create(Amount - FBalance);
FBalance := FBalance - Amount;
end;14.4 Global Exception Handling and Best Practices
Abort raises EAbort, which stops processing silently (no message dialog).
Exception.RaiseOuterException(...) / E.InnerException chains exceptions.
Tools: madExcept and EurekaLog for detailed crash reports with call stacks. JclDebug (JEDI) for stack traces.
Best practices: protect every created object with try..finally, catch specific exceptions, don't swallow exceptions, use Assert for programmer errors ({$C+} assertions).
// VCL: TApplicationEvents.OnException or Application.OnException
procedure TMainForm.AppException(Sender: TObject; E: Exception);
begin
LogToFile(E);
Application.ShowException(E);
end;