Ada: Exceptions
Ada's exception mechanism reports and recovers from run-time failures with named, catchable events. Every automatic check in the language — ranges, bounds, division by zero, null access — raises a named exception at the exact point of failure. Nothing fails silently.
Raise and Handle
Exceptions are ordinary declared objects. raise signals one; a block's exception part handles it:
with Ada.Text_IO; use Ada.Text_IO;
procedure Exception_Demo is
Overflow : exception; -- a user-defined exception
function Divide (A, B : Integer) return Integer is
begin
if B = 0 then
raise Overflow with "division by zero requested"; -- attach a message
end if;
return A / B;
end Divide;
begin
Put_Line (Integer'Image (Divide (10, 0)));
exception -- handler for THIS unit
when E : Overflow =>
Put_Line ("caught: " & Exception_Message (E)); -- "division by zero requested"
end Exception_Demo;
E : Overflow names the occurrence so the handler can read its message and identity (Exception_Identity (E) distinguishes occurrences of the same exception).
Propagation
An unhandled exception unwinds frames until some caller handles it. Code after the raise never runs in that frame:
procedure Propagation_Demo is
begin
begin
raise Constraint_Error; -- simulate a failure
Put_Line ("skipped"); -- never executes
exception
when Storage_Error => null; -- not ours: propagates further out
end;
-- ...the inner handler did not match, so this point is never reached
-- unless an OUTER handler catches what escaped.
end Propagation_Demo;
Predefined Exceptions
The language raises these automatically — you mostly handle them rather than raise them:
| Exception | Raised when |
|---|---|
Constraint_Error | a range, index, or null-exclusion check fails |
Program_Error | control reaches an impossible point (e.g. missing return) |
Storage_Error | the stack or heap is exhausted |
Tasking_Error | a task communication fails |
Library packages define their own (Name_Error, Data_Error in I/O), always declared in the package's specification — check the spec to know what to catch.
others and Last-Resort Handlers
when others => catches everything; its legitimate home is a top-level handler that logs and reports. Using it deep in the code hides bugs:
-- main program of a long-running system:
-- exception
-- when E : others =>
-- Log ("unhandled " & Exception_Name (E)); -- name, not just message
-- raise; -- re-raise: never swallow
The bare raise; inside a handler re-raises the same occurrence — the standard idiom for "log and continue propagating." Next: Generics.