Re: Exceptions and out procedure arguments (using GNAT GPL)
- From: Fionn Mac Cumhaill <invisible@xxxxxxxxxxxxxxxx>
- Date: Tue, 19 Jun 2007 05:23:51 GMT
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.
.
- Follow-Ups:
- Re: Exceptions and out procedure arguments (using GNAT GPL)
- From: Randy Brukardt
- Re: Exceptions and out procedure arguments (using GNAT GPL)
- From: Maciej Sobczak
- Re: Exceptions and out procedure arguments (using GNAT GPL)
- References:
- Exceptions and out procedure arguments (using GNAT GPL)
- From: Fionn Mac Cumhaill
- Re: Exceptions and out procedure arguments (using GNAT GPL)
- From: Adam Beneschan
- Exceptions and out procedure arguments (using GNAT GPL)
- Prev by Date: Re: Amount of copying on returned constant objects
- Next by Date: Re: Exceptions and out procedure arguments (using GNAT GPL)
- Previous by thread: Re: Exceptions and out procedure arguments (using GNAT GPL)
- Next by thread: Re: Exceptions and out procedure arguments (using GNAT GPL)
- Index(es):
Relevant Pages
|