Re: Exceptions and out procedure arguments (using GNAT GPL)



On Mon, 18 Jun 2007 08:44:57 -0700, Adam Beneschan <adam@xxxxxxxxxx>
wrote:

On Jun 15, 6:05 pm, Fionn Mac Cumhaill <invisi...@xxxxxxxxxxxxxxxx>
wrote:
Consider a procedure that starts like this:

procedure My_Procedure (
O: out integer
)
is
begin

-- various statements follow

O := 999;

-- more statements follow

raise My_Exception;

I'm using GNAT GPL.

My question is:

Is the routine which calls My_Procedure guaranteed to get a value if
it does something like this?

X := 0;
My_Procedure(X);

and has an exception handler

exception
when My_Exception =>
null;

Will X get a value of 999?

No. When My_Procedure completes abnormally, due to an exception
raise, X should have the value that it had before My_Procedure was
called. An Ada compiler that causes X to be 999 here (if it wasn't
999 before) is incorrect. This isn't a matter of "is the compiler
allowed to optimize" or "all bets are off" or "you can't rely on the
value"; rather, the semantics *require* that X be unchanged. This is
because O is a by-copy parameter (6.2(3)), which means that inside the
subprogram, O denotes a *separate* object from X (6.2(2)), and O is
copied back to X only on *normal* completion of the subprogram
(6.4.1(17)), but an exception raise causes My_Procedure to be
completed abnormally (7.6.1(2)).

By-reference parameters work differently. If, for example, your OUT
parameter were a tagged record, and you had assigned a component of it
to 999, it should still be 999 even after the exception in
My_Procedure is raised. As I interpret the rules in 11.6, this might
not be the case if the exception raise is due to a language-defined
check; if, after you assign the component to 999, you do an array
access on a nonexistent element, so that Constraint_Error is raised,
this is a language-defined check, and now I think the compiler may be
allowed to optimize in a way so that the assignment of the component
to 999 might not take place. But in your example, you have an
explicit raise of a user-defined exception, and 11.6 doesn't apply to
those, as I read it. The same would apply in an access parameter
case; if My_Procedure is abandoned due to a raise of a user-defined
exception, you can count on any assignments that you've already done
through the access value, but you can't count on assignments done
before My_Procedure is abandoned due to a language-defined check.

Hope this helps,
-- Adam


It does indeed help, and convinces me that GNAT GPL 2007 has a bug.
The example I gave is a highly condensed version of a problem I had
while working on upgrading the MySQL binding in GNADE to work with
MySQL 5. I found after posting my first message that the situation is
even more confusing than I thought it was.

Having (more or less) completed the work on the binding, I proceeded
to lay another package on top of it so that I could have something
that closely resembled the database package in GWindows. This would
greatly simplify the task of moving a lot of Windows software to
Linux. The sample is a highly condensed version of my Query procedure
which raises an exception when a query sent to the MySQL database
server returns no rows. The O argument in my sample is actually a
handle whisch is used by other routines which extract data from the
columns in the returned row set.The routine that uses My_Procedure to
set the value of X is a procedure in the additional package. Let's
call it My_Outer_Procedure. I have two test programs that use a query
which returns no rows.

What I have found is, in effect, that whether X is 0 or 999 depends on
something in the routine that calls My_Outer_Procedure. I have two
test programs which use a query which produces no rows, which means
that My_Procedure always raises an exception. In one of the test
programs, X is 0, and in the other it is 999, which makes no sense to
me.

I eliminated the problem by modifying the offending procedure to not
raise exceptions. It now returns a status code in an additional out
argument.



.



Relevant Pages

  • Re: Exceptions and out procedure arguments (using GNAT GPL)
    ... raise exceptions. ... But it might be the correct design anyway. ... subprogram will raise an exception AND the caller can expect a certain ... to hold information about the result set returned by the query. ...
    (comp.lang.ada)
  • Re: Exceptions and out procedure arguments (using GNAT GPL)
    ... raise My_Exception; ... and has an exception handler ... An Ada compiler that causes X to be 999 here (if it wasn't ... you can count on any assignments that you've already done ...
    (comp.lang.ada)
  • Re: contracted exceptions
    ... silently dies -- without notifying anyone. ... Enforcing the subprograms ... superior to the existing rule of silently ignoring the exception. ... Or raise Program_Error in the parent task at the point where that task ...
    (comp.lang.ada)
  • Re: ascii to tword - help
    ... if(cmp128(inputL, ... Raise($1_1285); ... we succeeded if we got this exception. ...
    (alt.lang.asm)
  • Re: AssignFile, Reset und IOResult 103
    ... on exception do ... Raise ESecHashException.Create('File not found! ... Raise ESecHashException.CreateFmt('Could not open File ''%s''.'#13#13' ... Die beiden Dateinamen haben definitiv nichts miteinander zu tun. ...
    (de.comp.lang.delphi.misc)