PolarBear2015
PolarBear2015

Reputation: 844

ADA: How to catch an exception that is raised during object instantiation?

An exception can be raised during an instantiation of an object in the declaration part.

For example, the code below raises a Storage_Error exception cause by an (intentional) stack overflow.

How can I catch this exception?

(My attempts to put exception handling in the body of the object that is instantiated, as well as in the procedure that instantiate the object failed to catch the exception that is raised during instantiation.)

Thank you!

---------------------- foo.ads -----------------------
generic
   Size : Natural;
package Foo is
    type Integer_Array is Array (1..Size) of Integer;
    buffer : Integer_Array;
end Foo;
---------------------- foo.adb -----------------------
With Text_IO; use Text_IO;
package body Foo is
begin
    exception -- Failed attempt 
        when storage_error =>
            Put_line("Foo: Storage Error");
        when others =>
            Put_line("Foo: Other Error");
end Foo;
---------------------- bar.adb -----------------------
with Text_IO; use Text_IO;
With Foo;

procedure Bar is
    package object is new Foo (Size => 10_000_000);
begin
    Put_line("Dummy Statement");
    exception -- Failed attempt as well
    when storage_error =>
        Put_line("Bar: Storage Error");
    when others =>
        Put_line("Bar: Other Error");
end Bar;

Upvotes: 3

Views: 842

Answers (2)

Jeffrey R. Carter
Jeffrey R. Carter

Reputation: 3358

Ada has many constructs of the form

<head part for Name> is
   <declarations>
begin
   <executable statements>
exception
   <exception handlers>
end Name;

The rule is that the exception handlers can only handle exceptions raised by the executable statements, so this set of exception handlers cannot handle an exception in the declarations.

To handle an exception in a declaration, that declaration has to be part of an executable statement. The most common way to do this is to use a block statement:

begin
   Inner : declare
      <declarations>
   begin
      <executable statements>
   end Inner;
exception
   <exception handlers>
end Name;

Now the block statement Inner is part of Name's executable statements, so any exception raised in Inner's declarations can be handled by Name's exception handlers.

This may seem arbitrary, but it is often useful to be able to refer to declaractions in exception handlers, and an exception in the declarations can leave declarations unelaborated. Therefore, the language designers decided to limit the scope of the exception handlers to the executable statements, so that you can be sure all declarations have been elaborated if you handle an exception. (In the example, Name's exception handlers cannot refer to Inner's declarations, so this is not an issue.)

Upvotes: 2

DeeDee
DeeDee

Reputation: 5941

You need to catch the exception in the subprogram that calls Bar. See also the attention box in section Handling an Exception on learn.adacore.com. A slightly adapted version of the example given in the attention box:

with Ada.Text_IO;    use Ada.Text_IO;
with Ada.Exceptions; use Ada.Exceptions;

procedure Be_Careful is

   function Dangerous return Integer is
   begin
      raise Constraint_Error;
      return 42;
   end Dangerous;

begin

   declare
      A : Integer := Dangerous;
   begin
      Put_Line (Integer'Image (A));
   exception
      when Constraint_Error => Put_Line ("missed!");
   end;

exception
   when Constraint_Error => Put_Line ("caught!");
end Be_Careful;

Upvotes: 5

Related Questions