[comp.lang.ada] Updating IN OUT's after exceptions

stuartw@tove.cs.umd.edu (Stuart M. Weinstein) (04/30/91)

In the enclosed program, I raise an exception inside a subroutine after
making an assignment to an IN OUT parameter.  In the first case, the
parameter is a scalar, in the second it is not.  Everything else is the
same, except the resulting behavior.  Is this permitted by the LRM?
I know that compilers can pass non-scalar parameters by copy-in/copy-out
or reference, but should that effect exception handling?  Is Ada/9x
addressing this?

Thanks.

Stuart.  (weinstei@kong.gsfc.nasa.gov)


with text_io;
procedure t1 is

  type intarr is array(1..50) of integer;
  zero : integer;
  a    : integer;
  arr  : intarr;

  procedure sub1(x : in out integer) is
    y : integer := 1;
  begin
    x := x + 10;
    y := y / zero; -- raise exception
  end sub1;

  procedure sub2(x : in out intarr; i : in integer) is
    y : integer := 1;
  begin
    x(i) := x(i) + 10;
    y    := y / zero; -- raise exception
  end sub2;

begin

  zero := 0;
  a := 5;
  text_io.put_line("Before sub1: A = " & integer'image(a));
  begin sub1(a); exception when others => null; end;
  text_io.put_line("After  sub1: A = " & integer'image(a));

  arr(12) := 5;
  text_io.put_line("Before sub1: ARR(12) = " & integer'image(arr(12)));
  begin sub2(arr,12); exception when others => null; end;
  text_io.put_line("After  sub1: ARR(12) = " & integer'image(arr(12)));

end;

Output from DEC Ada 2.2:

Before sub1: A =  5
After  sub1: A =  5
Before sub1: ARR(12) =  5
After  sub1: ARR(12) =  15

stt@inmet.inmet.com (05/02/91)

Re:  Updating IN OUT's after exceptions 
         Query on  5:18 am  Apr 30, 1991 by stuartw@tove.cs.umd.edu

> In the enclosed program, I raise an exception inside a subroutine after
> making an assignment to an IN OUT parameter.  In the first case, the
> parameter is a scalar, in the second it is not.  Everything else is the
> same, except the resulting behavior.  Is this permitted by the LRM?
> I know that compilers can pass non-scalar parameters by copy-in/copy-out
> or reference, but should that effect exception handling?  Is Ada/9x
> addressing this?
> 
> Thanks.
> 
> Stuart.  (weinstei@kong.gsfc.nasa.gov)

The Good Old Reference Manual, section 6.2:12 says the following:
  If the execution of a subprogram is abandoned as a result of an exception,
  the final value of an actual parameter [...] can be either its
  value before the call [if passed by copy] or a value assigned
  to the formal parameter during the execution of the subprogram
  [if passed by reference].

In other words, the compiler "does the right thing."

S. Tucker Taft
Intermetrics, Inc.
Cambridge, MA  02138

smithd@software.org (Doug Smith) (05/03/91)

In article <20600103@inmet> stt@inmet.inmet.com writes:
> 
> Re:  Updating IN OUT's after exceptions 
>          Query on  5:18 am  Apr 30, 1991 by stuartw@tove.cs.umd.edu
> 
> > In the enclosed program, I raise an exception inside a subroutine after
> > making an assignment to an IN OUT parameter.  In the first case, the
> > parameter is a scalar, in the second it is not.  Everything else is the
> > same, except the resulting behavior.  Is this permitted by the LRM?
> > I know that compilers can pass non-scalar parameters by copy-in/copy-out
> > or reference, but should that effect exception handling?  Is Ada/9x
> > addressing this?
> > 
> > Thanks.
> > 
> > Stuart.  (weinstei@kong.gsfc.nasa.gov)
> 
> The Good Old Reference Manual, section 6.2:12 says the following:
>   If the execution of a subprogram is abandoned as a result of an exception,
>   the final value of an actual parameter [...] can be either its
>   value before the call [if passed by copy] or a value assigned
>   to the formal parameter during the execution of the subprogram
>   [if passed by reference].
> 
> In other words, the compiler "does the right thing."
> 
> S. Tucker Taft
> Intermetrics, Inc.
> Cambridge, MA  02138

I have adopted a rather obvious programming style to avoid this
ambiguity, and to help maintain data integrity (an even higher
priority):

    Do not change an 'in out' parameter until there is little to
    no chance of an exception being raised.  This can be accomplished
    two ways:
       o  First! Explicitly check for exceptional conditions and
          raise the exception before attempting to update an
          'in out' parameter.  This is essential for limited
          private types that have no assignment procedure (see
          next bullet).
       o  Use additional local variables to hold intermediate
          results, and don't forget to clean up any garbage that
          might be generated (you may exit the routine normally or
          through the exception handler!).

    Don't forget that passing a formal parameter as parameter
    to another routine could modify it then raise an exception!
    Not everyone holds to the high morals of data integrity
    (nor can they afford to when performance is critical).

Some of you may not have this luxury (i.e. hard-real-time
applications programmers), but I extend this guideline to array
parameters!  That means, if necessary, copying the formal
parameter to a local array, modifying the local array, then
if no exceptions were raised, copying the local array back
to the formal parameter (immediately before exiting the
routine).

Of course, I avoid this almost all of the time by using
the 'First!' bullet described above.  Then, since most
array usage can be isolated to generic data structure
utilities (iterators, selectors, constructors galore!), I
almost never deal with arrays directly.

There are several issues of data integrity to deal with
when the limited private types are implemented as pointers
(to arrays), but let's not delve too deep...

lee@leo (Bill Lee) (05/03/91)

In article <20600103@inmet> stt@inmet.inmet.com writes:
>
>Re:  Updating IN OUT's after exceptions 
>         Query on  5:18 am  Apr 30, 1991 by stuartw@tove.cs.umd.edu
>
>> In the enclosed program, I raise an exception inside a subroutine after
>> making an assignment to an IN OUT parameter.  In the first case, the
>> parameter is a scalar, in the second it is not.  Everything else is the
>> same, except the resulting behavior.  Is this permitted by the LRM?
>> I know that compilers can pass non-scalar parameters by copy-in/copy-out
>> or reference, but should that effect exception handling?  Is Ada/9x
>> addressing this?
>> 
>> Thanks.
>> 
>> Stuart.  (weinstei@kong.gsfc.nasa.gov)
>
>The Good Old Reference Manual, section 6.2:12 says the following:
>  If the execution of a subprogram is abandoned as a result of an exception,
>  the final value of an actual parameter [...] can be either its
>  value before the call [if passed by copy] or a value assigned
>  to the formal parameter during the execution of the subprogram
>  [if passed by reference].
>
>In other words, the compiler "does the right thing."
>
>S. Tucker Taft
>Intermetrics, Inc.
>Cambridge, MA  02138


The "Right Thing"??? Yes,.....but.....

THERE ARE NO GUARANTEES THAT ANY TWO COMPILERS WILL DO IT THE SAME!

Any program that depends on a particular implementation of the values
returned (or not returned) in a record or array under the conditions
specified is technically erroneous. Sure, it will work on the first
compiler/platform, but there is no way to believe that it will work
elsewhere.

Bill Lee			lee@shell.com
Shell Oil Co.