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=-0.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,c4cb2c432feebd9d X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!news3.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!nx01.iad01.newshosting.com!newshosting.com!newsfeed.icl.net!newsfeed.fjserv.net!newsfeed.arcor.de!newsspool2.arcor-online.net!news.arcor.de.POSTED!not-for-mail From: "Dmitry A. Kazakov" Subject: Re: Finalization Newsgroups: comp.lang.ada User-Agent: 40tude_Dialog/2.0.15.1 MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Reply-To: mailbox@dmitry-kazakov.de Organization: cbb software GmbH References: <0ugu4e.4i7.ln@hunter.axlog.fr> <%P_cg.155733$eR6.26337@bgtnsc04-news.ops.worldnet.att.net> <6H9dg.10258$S7.9150@news-server.bigpond.net.au> <1hfv5wb.1x4ab1tbdzk7eN%nospam@see.signature> <2006052509454116807-gsande@worldnetattnet> Date: Tue, 21 Nov 2006 10:22:59 +0100 Message-ID: NNTP-Posting-Date: 21 Nov 2006 10:22:59 CET NNTP-Posting-Host: 95ca2316.newsspool2.arcor-online.net X-Trace: DXC=XV=mA=>:n\BH3YbicoVmhY2?PeDNcfSJ;bb[eFCTGGVUmh?dN\HXHJ4e80n7>kRMVh3FEd X-Complaints-To: usenet-abuse@arcor.de Xref: g2news2.google.com comp.lang.ada:7595 Date: 2006-11-21T10:22:59+01:00 List-Id: On Tue, 21 Nov 2006 10:02:35 +0100, Philippe Tarroux wrote: > I have a problem trying to use controlled types. My purpose was to use > finalize to deallocate a big data structure each time a reuse. > > I wrote a simpler program that exhibits the problem too. here is the > code followed by a comment on what I observed: > > with Ada.Unchecked_Deallocation, > Ada.Finalization; > > package Final is > type Vector is array (Positive range <>) of Float; > type Vector_Ptr is access Vector; > > procedure Free is new Ada.Unchecked_Deallocation (Vector, Vector_Ptr); > > type Obj is new Ada.Finalization.Controlled with record > X : Vector_Ptr := null; > end record; Note that Obj is declared Controlled, not Limited_Controlled, therefore the function Process would make a copy of it. When you are dealing with copies of pointers (the field X), you should decide what you would do with multiple pointers to the same object, especially upon finalization. In any case you have to override Adjust (and probably use reference counting). But I suppose it should better be Limited_Controlled. > overriding > procedure Finalize (O : in out Obj); > procedure Process (O : in out Obj); > function Process return Obj; > end Final; > > > with Ada.Text_Io; > > package body Final is > package Text_Io renames Ada.Text_Io; > > procedure Finalize (O : in out Obj) is > begin > Text_Io.Put ("Finalize: "); Text_Io.New_Line; (Use Put_Line for that) > Free (O.X); > end Finalize; > > procedure Process (O : in out Obj) is > begin > Text_Io.Put ("In process procedure"); Text_Io.New_Line; > Finalize(O); You don't need that. It breaks your design. As a rule, Finalize should be called once, and almost never explicitly. > O.X := new Vector (1 .. 100); > end Process; > > function Process return Obj is > O : Obj; > begin > Text_Io.Put ("In process function"); Text_Io.New_Line; > O.Process; > return O; > end Process; This is broken. You allocate a new vector in Process, then a shallow copy of is made in "return 0." Then O is destructed and as a result Finalize kills that vector. The caller receives the shallow copy object with a dangling pointer in the filed X. > end Final; > > with Ada.Text_Io, > Final; > > procedure main is > O : Final.Obj; > begin > for I in 1 .. 100 loop > Ada.Text_Io.put(Integer'Image(I)); Ada.Text_Io.New_Line; > O := Final.Process; > -- O.Process; > end loop; Do it this way: for I in 1 .. 100 loop declare O : Obj; -- Ideally Initialize should allocate the vector begin Process (O); -- Don't allocate anything here end; -- Finalize takes care of vector end loop; > Ada.Text_Io.put(Integer'Image(I)); Ada.Text_Io.New_Line; > O := Final.Process; > -- O.Process; > end loop; > Ada.Text_Io.Put("Fin"); Ada.Text_Io.New_Line; > end Main; > > and the resulting execution trace: > > 1 > In process function > In process procedure > Finalize: > Finalize: > Finalize: > Finalize: > 2 > and so on...until: > 7 > In process function > In process procedure > Finalize: > Finalize: > Finalize: > Finalize: > 8 > In process function > In process procedure > Finalize: > process exited with status 128 > > When I use the function call the program stops with an unexpected error > that seems to be different from one compiler to another (I tried gnat > gcc 3.4.6 on Windows and the Debian gnat version on Linux). The message > depends also on the type of structure to be freed (vector or > vector'class). Even when the program raises PROGRAM_ERROR I am unable > to trap the exception. I tried to follow what happens under gdb and > observed that an unexpected signal cencerning the heap is received by > the program. > > When i use the procedure call (commented out in the main program), all > is correct but I suspect that the memory is not deallocated at each call > in the main loop since there i s only one call to Finalize at the end of > the program. > > Does somebody has any idea of what happens? Do you think there is a > faulty construct in my code? Yes, see above. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de