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!.POSTED!not-for-mail From: Simon Wright Newsgroups: comp.lang.ada Subject: Re: Strings with discriminated records Date: Mon, 28 May 2018 08:42:21 +0100 Organization: A noiseless patient Spider Message-ID: References: <55ce14eb-6b83-4ea0-a550-f9e1410d0b06@googlegroups.com> <51dfb377-1b3e-45ca-a211-158101efe557@googlegroups.com> <090d6eb2-9f52-4471-a22e-ce1bdf457188@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: h2725194.stratoserver.net; posting-host="8b68575add0c7b121e6d1221acc2bceb"; logging-data="32537"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+F60O+1L6RVbznkH5qx985CiwBSZj4LFI=" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.3 (darwin) Cancel-Lock: sha1:95c1ew0CIHIOjRRUYJ37s55Uny0= sha1:jVqXJVr1XFlTcARQ06uLqO2MoO4= Xref: reader02.eternal-september.org comp.lang.ada:52748 Date: 2018-05-28T08:42:21+01:00 List-Id: NiGHTS writes: > I confirmed with an Ada.Text_IO.Put_Line() that Finalize was called > three times. 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? You need to read ARM7.6, in particular (17): http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-7-6.html#p17 Disregarding for the moment any "assignment" that might happen in computing the result of Create, & looking at declare M : Nights.Message := Nights.Create ("Hello World"); begin null; end; First, the Create call makes an anonymous object. Then, M is in theory finalized, but this is likely optimised away. Then, the bits of the anonymous object are copied into M. This is a "shallow copy". [***] Then, the anonymous object is finalized, which frees .Cstr. HOWEVER, M.Cstr still contains the same value, which means it's pointing to deallocated memory. Then, on exit from the declare block, M is finalized, and Finalize tries to free M.Cstr again. Oops. This is always going to happen if you make a shallow copy of something which contains plain allocated memory. As Dmitry said upthread, you need an Adjust, which makes a deep copy of the plain allocated memory, immediately after [***] above: procedure Adjust (M : in out Message) is use Interfaces.C.Strings; begin M.Cstr := New_Char_Array (Value (M.Cstr)); end Adjust; > 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. If the boolean was in Message, the same argument as above applies. > I'm perplexed. Not sure if I should ever trust > Ada.Finalization.Controlled. As with most things, not until you know how to use it.