Reputation: 844
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
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
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