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.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,b7566e485e23e171 X-Google-Attributes: gid103376,public From: bobduff@world.std.com (Robert A Duff) Subject: Re: Changing discriminants at run-time: erroneous execution? Date: 1996/08/07 Message-ID: #1/1 X-Deja-AN: 172682124 references: organization: The World Public Access UNIX, Brookline, MA newsgroups: comp.lang.ada Date: 1996-08-07T00:00:00+00:00 List-Id: In article , Andre Spiegel wrote: >The following program prints a strange result (using GNAT 3.05 under >Ultrix), as indicated in the comments. I know that this is not the >recommended way to create dynamic arrays, but I'm actually surprised >that the program passes the compiler (warning at line 8: "creation of >object of this type may raise Storage_Error"), and then silently >produces a wrong result at runtime. You probably have stack overflow (Storage_Error) checking turned off. I think it's off by default -- check the docs. The warning isn't kidding -- GNAT will allocate the max size for this sort of record. Since the RM doesn't say anything about how much storage is allocated for anything, GNAT is well within its rights to allocate the max. And if you have a check turned off, and violate that check, it's erroneous. So long as GNAT provides some way of turning on the checks, it is OK. (I would prefer that all checks be on by default, but the ACT folks say it's too inefficient. In any case, the RM doesn't say anything about that.) You probably already know this, but you might want to check out the Strings.Bounded package. > type Buffer (Size : Natural := 3) is Declare a more reasonable size here. E.g.: type Size_Type is range 0..100; type Buffer (Size: Size_Type := 3) is ... > record > Value : String (1..Size); > end record; > > Message : Buffer; >But 3.7.2(4) goes on to say > > The execution of a construct is erroneous if the construct has a > constituent that is a name denoting a subcomponent that depends on > discriminants, and the value of any of these discriminants is changed > by this execution between evaluating the name and the last use > (within this execution) of the subcomponent denoted by the name. > >Does this apply in the above situation? No. This is a much more obscure case -- things like: function F return Character is begin Message := (Size => 2, Value => "xx"); -- Evil side effect! return '*'; end F; Message.Value(3) := F; -- Erroneous. >... It is clear that the run-time >system would have to do silent heap allocation to support "resizing" >the array, but if it is not prepared to do so (as GNAT seems to be), >why is the erroneous execution permitted by the RM? Some compilers do the silent heap allocation, some do not. GNAT does not. In portable code, you will have to assume an allocate-the-max implementation. There have been discussions in the past about which implementation approach is better. >The interesting thing is that Barnes' Ada 95 book has examples that >use this precise "feature" (dynamic resizing of arrays, pp. 340). It >doesn't note any potential problems. Also, the example RM 3.7.1 (15) >at least *suggests* that "resizing" such arrays should work: > > Message : Buffer; -- unconstrained, initially 100 characters > -- (default discriminant value) In your example, the max size is 2**31-1 characters. In this RM example, the maximum size of the inner array is 500 characters. So it's not surprising that one raises S_E and the other doesn't. ;-) I don't have Barnes' book in front of me, but it should have a similar limit. By the way, the RM example is scattered across four sections: 3.3.2(10), 3.5.4(35), 3.7(33), and 3.7.1(15). I tracked it all down using the Index. - Bob