comp.lang.ada
 help / color / mirror / Atom feed
* Limited_Controlled and out parameters
@ 2012-06-22 13:37 Maciej Sobczak
  2012-06-22 15:43 ` Adam Beneschan
  0 siblings, 1 reply; 7+ messages in thread
From: Maciej Sobczak @ 2012-06-22 13:37 UTC (permalink / raw)


I have found a conceptual problem with the rules for Limited_Controlled types when they are used as out parameters in subprograms.

Consider:

   type Int_Ptr is access Integer;
   type Int_Holder is new Limited_Controlled with record
      I : Int_Ptr;
   end record;

The intent is that the Int_Holder can optionally hold an integer value. Optionally means that it might as well be empty (null);

Then:

   procedure Set (H : out Holder; Value : in Integer) is
   begin
      H.I := new Integer'(Value);
   end Set;

All is fine and the conveniently overriding procedure Finalize cleans the mess at the end.
The problem is that the Set procedure can be called many times in a row:

   Set (H, 7);
   Set (H, 8);
   -- ...

Each time it is called on the same H (Holder) object, a new Integer is allocated - this is a memory leak.
A possible solution is to check if the holder already contains some value and deallocate it before planting a new one. The problem is - this is an *out* parameter and notionally it is uninitialized. Well, controlled types are passed by reference, so it *would* work fine, but that's just cheating (and a more strict data flow would reject it as a clear violation).

What's the proper solution?

-- 
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Limited_Controlled and out parameters
  2012-06-22 13:37 Limited_Controlled and out parameters Maciej Sobczak
@ 2012-06-22 15:43 ` Adam Beneschan
  2012-06-22 16:58   ` J-P. Rosen
  2012-06-22 20:22   ` Randy Brukardt
  0 siblings, 2 replies; 7+ messages in thread
From: Adam Beneschan @ 2012-06-22 15:43 UTC (permalink / raw)


On Friday, June 22, 2012 6:37:31 AM UTC-7, Maciej Sobczak wrote:
> I have found a conceptual problem with the rules for Limited_Controlled types when they are used as out parameters in subprograms.
> 
> Consider:
> 
>    type Int_Ptr is access Integer;
>    type Int_Holder is new Limited_Controlled with record
>       I : Int_Ptr;
>    end record;
> 
> The intent is that the Int_Holder can optionally hold an integer value. Optionally means that it might as well be empty (null);
>
> Then:
> 
>    procedure Set (H : out Holder; Value : in Integer) is
>    begin
>       H.I := new Integer'(Value);
>    end Set;
> 
> All is fine and the conveniently overriding procedure Finalize cleans the mess at the end.
> The problem is that the Set procedure can be called many times in a row:
> 
>    Set (H, 7);
>    Set (H, 8);
>    -- ...
> 
> Each time it is called on the same H (Holder) object, a new Integer is allocated - this is a memory leak.
> A possible solution is to check if the holder already contains some value and deallocate it before planting a new one. The problem is - this is an *out* parameter and notionally it is uninitialized. Well, controlled types are passed by reference, so it *would* work fine, but that's just cheating (and a more strict data flow would reject it as a clear violation).

(I assume that Int_Holder and Holder were intended to be the same type rather than two different types).

Off the top of my head, I'd say that since Int_Ptr can be modified and since it's causing the memory leak, then you should use a Controlled (not Limited_Controlled) type instead of Int_Ptr.  Then it will be finalized whenever the I component is reassigned.

I also wouldn't worry about "cheating".  For by-reference parameters, I don't think there's that much difference between OUT and IN OUT, if any.  It really can't be, because if you have a procedure (or, now, a function) with an OUT parameter of a controlled type, the procedure still has to be able to (implicitly) read the "input" value of the parameter in order to finalize it before it's assigned.  So the idea that a procedure should treat an OUT parameter as if its value is garbage until the procedure assigns something to it doesn't work any more.  It was different in Ada 83, where there was no such thing as a parameter that *had* to be passed by reference, and the rules said that a procedure couldn't read the value of an OUT parameter except for bounds and discriminants.  But Ada 95 introduced parameters that were required to be passed by reference; in those cases, I don't think they're "notionally uninitialized" any more.

                       -- Adam




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Limited_Controlled and out parameters
  2012-06-22 15:43 ` Adam Beneschan
@ 2012-06-22 16:58   ` J-P. Rosen
  2012-06-22 19:12     ` Adam Beneschan
  2012-06-22 20:22   ` Randy Brukardt
  1 sibling, 1 reply; 7+ messages in thread
From: J-P. Rosen @ 2012-06-22 16:58 UTC (permalink / raw)


Le 22/06/2012 17:43, Adam Beneschan a �crit :

> I also wouldn't worry about "cheating".  For by-reference parameters,
> I don't think there's that much difference between OUT and IN OUT, if
> any. [...]
From the point of view of the implementer, you are right. However, by
having an OUT parameter, you are telling your user: "I don't use the
value in your variable; even if it is uninitialized, it's OK".

There is some value to preserving that aspect.
-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Limited_Controlled and out parameters
  2012-06-22 16:58   ` J-P. Rosen
@ 2012-06-22 19:12     ` Adam Beneschan
  2012-06-22 21:41       ` Robert A Duff
  0 siblings, 1 reply; 7+ messages in thread
From: Adam Beneschan @ 2012-06-22 19:12 UTC (permalink / raw)


On Friday, June 22, 2012 9:58:31 AM UTC-7, J-P. Rosen wrote:
> Le 22/06/2012 17:43, Adam Beneschan a écrit :
> 
> > I also wouldn't worry about "cheating".  For by-reference parameters,
> > I don't think there's that much difference between OUT and IN OUT, if
> > any. [...]
> From the point of view of the implementer, you are right. However, by
> having an OUT parameter, you are telling your user: "I don't use the
> value in your variable; even if it is uninitialized, it's OK".

Can a controlled variable (or subcomponent) ever really be uninitialized?  I guess it might, or it might be partly uninitialized.  However, if the controlled type has a Finalize routine that reads components of the type, those components had darn well better  not be uninitialized garbage.  (That is, allowing for cases where, say, a Boolean component indicates whether other components in the record are initialized or not.  But that Boolean had better not be garbage.)

                                 -- Adam



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Limited_Controlled and out parameters
  2012-06-22 15:43 ` Adam Beneschan
  2012-06-22 16:58   ` J-P. Rosen
@ 2012-06-22 20:22   ` Randy Brukardt
  2012-06-23 12:02     ` Maciej Sobczak
  1 sibling, 1 reply; 7+ messages in thread
From: Randy Brukardt @ 2012-06-22 20:22 UTC (permalink / raw)


"Adam Beneschan" <adam@irvine.com> wrote in message 
news:08532996-7c1f-4521-b1fc-41a03e26fcce@googlegroups.com...
...
> But Ada 95 introduced parameters that were required to be passed by 
> reference;
> in those cases, I don't think they're "notionally uninitialized" any more.

Actually, Ada 95 made a larger change (although a bit of it was already 
present in Ada 83): if the type of an Out parameter has explicit 
initialization, then it is *never* treated as uninitialized.  That's 
necessary as Ada 95 allows Out parameters to be read (that wasn't true in 
Ada 83). See 6.4.1(12-15/3). The only time that the formal parameter is 
uninitialized is the "otherwise" branch of this wording.

The OP's question is covered by 6.4.1(14): "For a composite type with 
discriminants or that has implicit initial values for any subcomponents (see 
3.3.1), the behavior is as for an in out parameter passed by copy."

Since his example includes a component with an access type, it is always 
included in this bullet, so the behavior of the parameter is the same for 
"in out" and "out". And thus it is safe and reasonable to check if the 
object is already in use.

So, no, there is no definitional problem. As J-P notes, from the calleRs 
perspective, the situation might be different (and thus "out" still provides 
value in the contract), but inside a subprogram, "in out" and "out" are the 
same on the majority of composite types (including all of them that contain 
access components). Don't use that as an excuse to allow leaking.

(And I agree, don't make these things limited unless you really must not 
allow assignment. It's not that hard to write a proper Adjust routine for a 
type like this one. "Limited poisoning" is a real problem in practice.)

                                               Randy.





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Limited_Controlled and out parameters
  2012-06-22 19:12     ` Adam Beneschan
@ 2012-06-22 21:41       ` Robert A Duff
  0 siblings, 0 replies; 7+ messages in thread
From: Robert A Duff @ 2012-06-22 21:41 UTC (permalink / raw)


Adam Beneschan <adam@irvine.com> writes:

> Can a controlled variable (or subcomponent) ever really be
> uninitialized?

In Ada, the concept of "uninitialized" applies only to scalars.
Access types are initialized by default.  And composite types
have no such notion -- you can only talk about whether none, some,
or all of their scalar subcomponents are initialized.

> I guess it might, or it might be partly uninitialized.  However, if the
> controlled type has a Finalize routine that reads components of the
> type, those components had darn well better not be uninitialized
> garbage.

Right, if scalar.

>...(That is, allowing for cases where, say, a Boolean component
> indicates whether other components in the record are initialized or not.
> But that Boolean had better not be garbage.)

Right.  You can give that Boolean a default.  Or you can make
sure default initialization never happens, for example, by using
unknown discriminants -- "(<>)".

- Bob



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Limited_Controlled and out parameters
  2012-06-22 20:22   ` Randy Brukardt
@ 2012-06-23 12:02     ` Maciej Sobczak
  0 siblings, 0 replies; 7+ messages in thread
From: Maciej Sobczak @ 2012-06-23 12:02 UTC (permalink / raw)


W dniu piątek, 22 czerwca 2012 22:22:57 UTC+2 użytkownik Randy Brukardt napisał:

[...]
> Since his example includes a component with an access type, it is always 
> included in this bullet, so the behavior of the parameter is the same for 
> "in out" and "out". And thus it is safe and reasonable to check if the 
> object is already in use.

Thank you very much for a thorough explanation, this now makes sense.
Still, the solution does not feel very comfortable - the language seems to be somewhat spoiled by such nuances. Is it OK to read "out" parameters? Well, it depends on things that are defined far away from the place in question.

> (And I agree, don't make these things limited unless you really must not 
> allow assignment. It's not that hard to write a proper Adjust routine for a 
> type like this one. "Limited poisoning" is a real problem in practice.)

I don't fully agree here - I would rather approach it the other way round: start from the most limited (pun intended) set of operations and add to them only when necessary. Automatic call to Finalize is not necessarily what I want to have in such places - the type in question might be much more complex than what I have presented and the problematic procedure need not rewrite the whole object. But then I would use "in out" mode to reflect the fact that the post-call state depends on pre-call value.

-- 
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2012-06-23 12:02 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-22 13:37 Limited_Controlled and out parameters Maciej Sobczak
2012-06-22 15:43 ` Adam Beneschan
2012-06-22 16:58   ` J-P. Rosen
2012-06-22 19:12     ` Adam Beneschan
2012-06-22 21:41       ` Robert A Duff
2012-06-22 20:22   ` Randy Brukardt
2012-06-23 12:02     ` Maciej Sobczak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox