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=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!feeder.eternal-september.org!aioe.org!.POSTED!not-for-mail From: "Dmitry A. Kazakov" Newsgroups: comp.lang.ada Subject: Re: Strings with discriminated records Date: Mon, 28 May 2018 09:29:06 +0200 Organization: Aioe.org NNTP Server Message-ID: References: <55ce14eb-6b83-4ea0-a550-f9e1410d0b06@googlegroups.com> <51dfb377-1b3e-45ca-a211-158101efe557@googlegroups.com> <090d6eb2-9f52-4471-a22e-ce1bdf457188@googlegroups.com> NNTP-Posting-Host: CvkHMVp693S8Z+lk11jyqg.user.gioia.aioe.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Complaints-To: abuse@aioe.org User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0 X-Notice: Filtered by postfilter v. 0.8.3 Content-Language: en-US Xref: reader02.eternal-september.org comp.lang.ada:52747 Date: 2018-05-28T09:29:06+02:00 List-Id: On 2018-05-28 00:44, NiGHTS wrote: > I confirmed with an Ada.Text_IO.Put_Line() that Finalize was called three times. It is called for three different objects. > I then disabled Finalize and created an explicitly called Finalize2 function and it worked fine. It's weird though because my program only elaborated the object once, so why did it finalize three times? Because you have three copies of the controlled object. Here is a fixed implementation with Adjust: ------------------------------------------------------- with Ada.Text_IO; use Ada.Text_IO; with Interfaces.C; use Interfaces.C; with Interfaces.C.Strings; use Interfaces.C.Strings; with Ada.Finalization; procedure Test is package P is type C_String is new Ada.Finalization.Controlled with private; function Create (Text : String) return C_String; overriding procedure Adjust (Text : in out C_String); overriding procedure Finalize (Text : in out C_String); private type C_String is new Ada.Finalization.Controlled with record Ptr : chars_ptr; end record; end P; package body P is function Create (Text : String) return C_String is begin Put_Line ("Creating:" & Text); return (Ada.Finalization.Controlled with New_String (Text)); end Create; procedure Adjust (Text : in out C_String) is begin if Text.Ptr = Null_Ptr then Put_Line ("Copying null string:"); else Put_Line ("Copying:" & Value (Text.Ptr)); Text.Ptr := New_String (Value (Text.Ptr)); end if; end Adjust; procedure Finalize (Text : in out C_String) is begin if Text.Ptr = Null_Ptr then Put_Line ("Finalizing null string:"); else Put_Line ("Finalizing:" & Value (Text.Ptr)); Free (Text.Ptr); end if; end Finalize; end P; use P; S1 : C_String := Create ("Hello"); begin null; end Test; ------------------------------------------------- It prints: Creating:Hello Copying:Hello Finalizing:Hello Copying:Hello Finalizing:Hello Finalizing:Hello Now the meaning of this: Creating:Hello -- Create Copying:Hello -- Copy local object (aggregate?) in Create Finalizing:Hello -- Finalize the local object in Create Copying:Hello -- Copy result of Create to S1 Finalizing:Hello -- Finalize the result of Create Finalizing:Hello -- Finalize S1 > I tried wrapping the body of finalize in a condition to force it to run only once, yet it still managed to run it again ignoring the boolean. I'm perplexed. Not sure if I should ever trust Ada.Finalization.Controlled. Yes, see the example. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de