From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,fdc38a13551814d X-Google-Attributes: gid103376,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news2.google.com!newsfeed2.dallas1.level3.net!news.level3.com!newsfeed-00.mathworks.com!nntp.TheWorld.com!not-for-mail From: Robert A Duff Newsgroups: comp.lang.ada Subject: Re: Allocators and memory reclamation Date: Mon, 28 Jan 2008 19:41:58 -0500 Organization: The World Public Access UNIX, Brookline, MA Message-ID: References: <4a2fe64e-ae34-4093-88ec-1dc612a9adbd@v29g2000hsf.googlegroups.com> NNTP-Posting-Host: shell01.theworld.com Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: pcls6.std.com 1201567321 16378 192.74.137.71 (29 Jan 2008 00:42:01 GMT) X-Complaints-To: abuse@TheWorld.com NNTP-Posting-Date: Tue, 29 Jan 2008 00:42:01 +0000 (UTC) User-Agent: Gnus/5.1008 (Gnus v5.10.8) Emacs/21.3 (irix) Cancel-Lock: sha1:exkZ2SPSQX/hZbXM2BJoQCkZVFE= Xref: g2news1.google.com comp.lang.ada:19643 Date: 2008-01-28T19:41:58-05:00 List-Id: Maciej Sobczak writes: > Hi, > > Consider the following: > > procedure Foo is > type Int_Ptr is access Integer; > P : Int_Ptr; > begin > P := new Integer; > P := new Integer; > P := new Integer; > end Foo; > > procedure Main is > begin > loop > Foo; > end loop; > end Main; > > In Foo above, three objects of type Integer are allocated and the > storage is taken from the storage pool associated with the Int_Ptr > access type. > What I understood before is that this storage pool is torn down when > the access type itself goes out of scope and it is also when the > memory is reclaimed. As a result no memory is leaked in the above code > - I can call Foo as many times as I want without any risk of running > out of memory. Some implementations might behave that way, but you should not rely on it. >...This is at least what I can observe with controlled > types. I don't understand what you mean about controlled types. There are none in the above example, and I don't know what example you have in mind. > The problem is that my understanding conflicts with what I've just > found in AARM (13.11): > "By default, the implementation might choose to have a single global > storage pool, which is used (by default) by all access types, which > might mean that storage is reclaimed automatically only upon partition > completion." The implementation is allowed to use a local pool for Int_Ptr, and reclaim the memory, but it is not required to. I think most implementations use a global pool by default. That's certainly the case with GNAT. To force the reclamation, you can say: for Int_Ptr'Storage_Size use 1000; -- or some number or: for Int_Ptr'Storage_Pool use My_Pool; where My_Pool gets reclaimed somehow (that's up to you). My_Pool might allocate its data on the stack, so it will be reclaimed. Or it might allocate its data on the global heap, and have a Finalize that reclaims it. Or some of each. I think implementations should not do such reclamation by default -- a global heap is a better default way to do things. > This means that the implementation might turn the above well-behaving > procedure into a memory leak. Is this correct? Well, yeah, but that's a strange way to put it. The above procedure is not well behaved, unless you are relying on some non-portable implementation-depdendent behavior. > Can I influence this behaviour to portably ensure that memory is > reclaimed when the access type goes out of scope? Yes. > Another question relates to the order of finalizing objects. If the > storage pool is torn down when the access type goes out of scope, is > the order of finalizing objects guaranteed? Finalization of heap objects happens when you do Unchecked_Deallocation. In addition, when an access type goes out of scope, all remaining objects (the ones you did not Unchecked_Deallocate) are finalized in an arbitrary order, but this does not free the memory. Finalization of heap objects has nothing to do with storage pools. It has to do with where the access type is declared, not when its pool is finalized. In implementation terms, each finalizable heap object is chained onto a doubly-linked list. U_D removes the object from the list, finalizes it, and frees the memory. When the access type goes out of scope, the implementation walks down the list and finalizes everything on it. There is one list per access type. Many variations of this scheme are possible, of course. - Bob