comp.lang.ada
 help / color / mirror / Atom feed
From: Robert A Duff <bobduff@shell01.TheWorld.com>
Subject: Re: Memory management clarification
Date: 26 Jul 2005 10:17:58 -0400
Date: 2005-07-26T10:17:58-04:00	[thread overview]
Message-ID: <wcc3bq11wix.fsf@shell01.TheWorld.com> (raw)
In-Reply-To: dc51dt$qi6$1@sunnews.cern.ch

Maciej Sobczak <no.spam@no.spam.com> writes:

> Hi,
> 
> Trying to learn a bit of Ada I came across a statement that memory
> allocated from the pool will be implicitly reclaimed when the acces
> variable used to reference it goes out of scope.

If you use the default storage pool(s), the language standard does not
specify when heap memory is reclaimed.  Most implementations do not
reclaim any such memory unless you explicitly call
Unchecked_Deallocation.

If you put "for T'Storage_Size use 1_000_000;", then implementations
should reclaim all memory allocated for type T when the scope of T is
left.  The *type* -- not individual variables of the type.  This is not
a very useful capability, because most access types need to be at
library level, so the memory won't be reclaimed until the whole program
is done.

You should look up user defined storage pools.  You can say:

    for T'Storage_Pool use My_Pool;

and then you can control when memory will be reclaimed.
You can reclaim all memory in My_Pool whenever you like -- but
beware dangling pointers.

> That's nice, but I would like to learn a bit more about the exact
> mechanics of this and about the guarantees that it can provide.
> 
> Let's say that there is some MyType definition and this:
> 
> type MyTypeRef is access MyType;
> 
> 1.
> 
> declare
>      X : MyTypeRef;
> begin
>     loop
>        X := new MyType;
>     end loop;  -- infinite loop just for the sake of discussion
> end;
> 
> Note that X does not goes out of scope when the loop is executing.
> Will the memory be reclaimed?

No.

>... When? What can be said about the memory
> consumption of such program? Is it bounded and guaranteed?

No.  Unless the implementation supports garbage collection,
you will eventually run out of memory.  Most implementations
do not support GC.

>... Is it
> necessarily larger than without the loop (just single allocation)?
> 
> 2.
> 
> loop
>     declare
>        X : MyTypeRef;
>     begin
>        X := new MyType;
>     end;
> end loop;
> 
> What now? Is this any different from the memory management point of view?

No.  X.all will never be reclaimed (on most implementations).  The only
difference here is that you're allocating only one object.

Suppose we added a call P(X) inside the begin/end.  And suppose P saves
X in a global variable.  The implementation cannot deallocate the memory
X points to, because that would leave a dangling pointer in the global
variable.  A garbage collector's job is to tell whether or not that
happened -- then it can reclaim all memory not reachable.  But most Ada
implementations don't do GC -- they just assume X.all *might* be
reachable, and never reclaim it unless you do U_D.

> 3.
> 
> declare
>     X : MyTypeRef;
> begin
>     X := new MyType;
>     X := new MyType;
>     X := new MyType;
>     X := new MyType;
>     -- ...
> end;
> 
> When is the memory reclaimed for each allocated object? At each
> subsequent assignment? Or maybe at the end of the block? Or even
> "sometime later"? Or maybe all subsequent assignments are eliminated by
> compiler?

Never.  (Well, "never" really means "when the process exits".)

> 4.
> 
> Is it possible to associate some function with object allocated by new,
> which would be called at the time (or maybe after) the object is
> reclaimed?
> Yes, I'm asking about destructors or finalizers.

Yes.  Look up "controlled types".  These allow you to associate a
Finalize operation with a type.  For local variables, Finalize will be
automatically called when the procedure is left.  For heap objects,
Finalize will be called when you do Unchecked_Deallocation (or, if you
never do U_D, when the program is done).

> 5.
> 
> Is it possible to "overload" new for MyType so that the X := new MyType;
> statement will do whatever *I* want it to do, including actual memory
> allocation? If yes, is it possible to hook on memory reclamation as well?

"new" does two things: allocate memory, and initialize it (explicitly or
implicltly).  You can't exactly "overload new", but you can use storage
pools as described above -- this gives you control over the memory
allocation part of "new".  The initialization still happens in the
normal way.

> 6.
> 
> What about reference cycles between dynamically allocated objects?
> 
> declare
>     type ListNode;
>     type ListNodeRef is access ListNode;
>     type ListNode is record
>        SomeData : Integer;
>        Other : ListNodeRef;
>     end record;
>     First, Second : ListNodeRef;
> begin
>     First := new ListNode;
>     First.all.SomeData := 7;
>     Second := new ListNode;
>     Second.all.SomeData := 8;
> 
>     First.all.Other := Second;
>     Second.all.Other := First; -- cycle
> end;
> 
> Will the memory be reclaimed?

Cycles don't make any difference.

- Bob



  parent reply	other threads:[~2005-07-26 14:17 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-07-26  9:57 Memory management clarification Maciej Sobczak
2005-07-26 10:38 ` Adrien Plisson
2005-07-26 14:19   ` Robert A Duff
2005-07-26 13:57 ` Frank J. Lhota
2005-07-26 14:21   ` Robert A Duff
2005-07-26 18:11     ` Frank J. Lhota
2005-07-26 14:17 ` Robert A Duff [this message]
2005-07-26 15:39   ` Maciej Sobczak
2005-07-26 17:45     ` Robert A Duff
replies disabled

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