Ada uses exceptions for error handling. Unlike many other languages, Ada speaks about raising, not throwing, an exception and handling, not catching, an exception.
Ada exceptions are not types, but instead objects, which may be peculiar to you if you're used to the way Java or Python support exceptions. Here's how you declare an exception:
Even though they're objects, you're going to use each declared exception object as a "kind" or "family" of exceptions. Ada does not require that a subprogram declare every exception it can potentially raise.
Raising an exception¶
To raise an exception of our newly declared exception kind, do the following:
Handling an exception¶
Next, we address how to handle exceptions that were raised by us or libraries that we call. The neat thing in Ada is that you can add an exception handler to any statement block as follows:
In the example above, we're using the
Exception_Message function from
Ada.Exceptions package. This function returns the message
associated with the exception as a string.
You don't need to introduce a block just to handle an exception: you can add it to the statements block of your current subprogram:
Exception handlers have an important restriction that you need to be careful about: Exceptions raised in the declarative section are not caught by the handlers of that block. So for example, in the following code, the exception will not be caught.
This is also the case for the top-level exception block that is part of the current subprogram.
Ada has a very small number of predefined exceptions:
Constraint_Erroris the main one you might see. It's raised:
- When bounds don't match or, in general, any violation of constraints.
- In case of overflow
- In case of null dereferences
- In case of division by 0
Program_Errormight appear, but probably less often. It's raised in more arcane situations, such as for order of elaboration issues and some cases of detectable erroneous execution.
Storage_Errorwill happen because of memory issues, such as:
- Not enough memory (allocator)
- Not enough stack
Tasking_Errorwill happen with task related errors, such as any error happening during task activation.
You should not reuse predefined exceptions. If you do then, it won't be obvious when one is raised that it is because something went wrong in a built-in language operation.