* Discriminated types with default discriminants @ 2005-11-03 15:50 Maciej Sobczak 2005-11-03 16:06 ` Martin Krischik ` (4 more replies) 0 siblings, 5 replies; 15+ messages in thread From: Maciej Sobczak @ 2005-11-03 15:50 UTC (permalink / raw) Hi, Consider this: procedure Hello is type Discriminated(Size : Integer := 10) is record Value : String (1..Size); end record; S : Discriminated; begin null; end Hello; Compiler (GNAT) gives me two warnings: 5. Value : String (1..Size); | >>> warning: creation of object of this type may raise Storage_Error 8. S : Discriminated; | >>> warning: Storage_Error will be raised at run-time Moreover, it keeps a promise and indeed the program raises STORAGE_ERROR at run-time. What's happening here? Why the object S is not created with 10 as the default discriminant? I can get rid of the second warning by declaring S as: S : Discriminated(10); Indeed - program runs fine (i.e. it does not raise any exception). What's the difference? I can get rid of the first warning with this: subtype MyInt is Integer; type Discriminated(Size : MyInt := 10) is -- ... What's the difference? -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/ ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Discriminated types with default discriminants 2005-11-03 15:50 Discriminated types with default discriminants Maciej Sobczak @ 2005-11-03 16:06 ` Martin Krischik 2005-11-03 23:10 ` Robert A Duff 2005-11-03 16:21 ` Ed Falis ` (3 subsequent siblings) 4 siblings, 1 reply; 15+ messages in thread From: Martin Krischik @ 2005-11-03 16:06 UTC (permalink / raw) Am 03.11.2005, 17:50 Uhr, schrieb Maciej Sobczak <no.spam@no.spam.com>: > Hi, > > Consider this: > > procedure Hello is > > type Discriminated(Size : Integer := 10) is > record > Value : String (1..Size); > end record; > > S : Discriminated; > > begin > null; > end Hello; > > > Compiler (GNAT) gives me two warnings: > > 5. Value : String (1..Size); > | > >>> warning: creation of object of this type may raise > Storage_Error > > 8. S : Discriminated; > | > >>> warning: Storage_Error will be raised at run-time > > > Moreover, it keeps a promise and indeed the program raises STORAGE_ERROR > at run-time. > > What's happening here? Why the object S is not created with 10 as the > default discriminant? Because you might store a larger object later. So - at least GNAT - allocate as much memory as needed for the larges possible object - thats 2 GB. Hint 1: unless this is homework: use Bounded_String or Unbounded_String - don't reinvent the wheel. Hint 2: try "type MyInt is range 0 .. 1000;" or whatever upper limit is sensible. Martin Links: http://en.wikibooks.org/wiki/Ada_Programming/Strings ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Discriminated types with default discriminants 2005-11-03 16:06 ` Martin Krischik @ 2005-11-03 23:10 ` Robert A Duff 2005-11-04 5:01 ` Jeffrey R. Carter 0 siblings, 1 reply; 15+ messages in thread From: Robert A Duff @ 2005-11-03 23:10 UTC (permalink / raw) "Martin Krischik" <krischik@users.sourceforge.net> writes: > Hint 1: unless this is homework: use Bounded_String or Unbounded_String > - > don't reinvent the wheel. Well, that's usually good advice, but I had a case where changing a single Bounded_String to my own buffer type increased speed by two orders of magnitude. It depends on the program, of course. Initializing Bounded_Strings is surprisingly slow. - Bob ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Discriminated types with default discriminants 2005-11-03 23:10 ` Robert A Duff @ 2005-11-04 5:01 ` Jeffrey R. Carter 0 siblings, 0 replies; 15+ messages in thread From: Jeffrey R. Carter @ 2005-11-04 5:01 UTC (permalink / raw) Robert A Duff wrote: > Well, that's usually good advice, but I had a case where changing a > single Bounded_String to my own buffer type increased speed by two > orders of magnitude. It depends on the program, of course. > Initializing Bounded_Strings is surprisingly slow. Yikes! Which compiler(s)? -- Jeff Carter "Now go away or I shall taunt you a second time." Monty Python & the Holy Grail 07 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Discriminated types with default discriminants 2005-11-03 15:50 Discriminated types with default discriminants Maciej Sobczak 2005-11-03 16:06 ` Martin Krischik @ 2005-11-03 16:21 ` Ed Falis 2005-11-03 17:28 ` Dmitry A. Kazakov ` (2 subsequent siblings) 4 siblings, 0 replies; 15+ messages in thread From: Ed Falis @ 2005-11-03 16:21 UTC (permalink / raw) GNAT attempts to allocate the maximum size when an object with a defaulted discriminant is declared, since different sized values can be assigned to it. The alternative, used in the old Alsys compilers, is to allocate for the defaulted size, then perform reallocation during assignment if a differently sized value is assigned. Both approaches are allowed implementations with different tradeoffs. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Discriminated types with default discriminants 2005-11-03 15:50 Discriminated types with default discriminants Maciej Sobczak 2005-11-03 16:06 ` Martin Krischik 2005-11-03 16:21 ` Ed Falis @ 2005-11-03 17:28 ` Dmitry A. Kazakov 2005-11-03 18:51 ` Jeffrey R. Carter 2005-11-04 3:27 ` Brian May 4 siblings, 0 replies; 15+ messages in thread From: Dmitry A. Kazakov @ 2005-11-03 17:28 UTC (permalink / raw) On Thu, 03 Nov 2005 16:50:12 +0100, Maciej Sobczak wrote: > Consider this: > > procedure Hello is > > type Discriminated(Size : Integer := 10) is > record > Value : String (1..Size); > end record; > > S : Discriminated; > > begin > null; > end Hello; > > > Compiler (GNAT) gives me two warnings: > > 5. Value : String (1..Size); > | > >>> warning: creation of object of this type may raise > Storage_Error > > 8. S : Discriminated; > | > >>> warning: Storage_Error will be raised at run-time > > > Moreover, it keeps a promise and indeed the program raises STORAGE_ERROR > at run-time. > > What's happening here? Why the object S is not created with 10 as the > default discriminant? > > I can get rid of the second warning by declaring S as: > > S : Discriminated(10); > > Indeed - program runs fine (i.e. it does not raise any exception). > What's the difference? > > I can get rid of the first warning with this: > > subtype MyInt is Integer; > type Discriminated(Size : MyInt := 10) is > -- ... > > What's the difference? No difference, just another GNAT's "feature", GNAT will raise Storage_Error at run-time. What will indeed make difference is this: subtype Expected_Sizes is Natural range 0..1000; type Discriminated (Size : Expected_Sizes := 10) is record Value : String (1..Size); end record; But better is to remove the default value. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Discriminated types with default discriminants 2005-11-03 15:50 Discriminated types with default discriminants Maciej Sobczak ` (2 preceding siblings ...) 2005-11-03 17:28 ` Dmitry A. Kazakov @ 2005-11-03 18:51 ` Jeffrey R. Carter 2005-11-03 23:08 ` Robert A Duff 2005-11-04 9:18 ` Maciej Sobczak 2005-11-04 3:27 ` Brian May 4 siblings, 2 replies; 15+ messages in thread From: Jeffrey R. Carter @ 2005-11-03 18:51 UTC (permalink / raw) Maciej Sobczak wrote: > type Discriminated(Size : Integer := 10) is > record > Value : String (1..Size); > end record; Aside : begin When I see something like this, I always wonder: What does a negative Size mean? To my mind, a negative Size is meaningless, and should not be allowed: Size : Natural end Aside; There are 3 cases with discriminants: 1. No default (object must be declared with explicit value) 2. Default, and object declared with explicit value 3. Default, and object declared without explicit value The 1st 2 cases are equivalent. The object must always have the same value for the discriminant. It can never change. The object is constrained. The last case means the discriminant can change. The object is unconstrained. Given subtype V_Index is Natural range 0 .. 255; type V_String (Length : V_Index := 0) is record Data : String (1 .. Length) := String'(1 .. Length => 'J'); end record; V : V_String; one can later change the Length of V: V := V_String'(Length => 23, Data => String'(1 .. 23 => 'C') ); There are 2 ways the compiler may implement this. Many compilers, including GNAT, allocate enough storage for the largest value, and then use parts of this storage depending on the current value of the discriminant. If the largest value is too big, such a declaration results in Storage_Error being raised. A few compilers will add a level of indirection, and store the variable-sized stuff elsewhere, reallocating storage when the amount available is not big enough. I think RR Software's Janus Ada compiler does this. With this scheme, you only get Storage_Error if you actually try to store a value that is too big. As with most implementation decisions, it's a trade off among complexity, space, and time. -- Jeff Carter "Now go away or I shall taunt you a second time." Monty Python & the Holy Grail 07 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Discriminated types with default discriminants 2005-11-03 18:51 ` Jeffrey R. Carter @ 2005-11-03 23:08 ` Robert A Duff 2005-11-04 0:08 ` Adam Beneschan 2005-11-04 9:18 ` Maciej Sobczak 1 sibling, 1 reply; 15+ messages in thread From: Robert A Duff @ 2005-11-03 23:08 UTC (permalink / raw) "Jeffrey R. Carter" <spam@spam.com> writes: > There are 2 ways the compiler may implement this. Many compilers, > including GNAT, allocate enough storage for the largest value, and then > use parts of this storage depending on the current value of the > discriminant. If the largest value is too big, such a declaration > results in Storage_Error being raised. > > A few compilers will add a level of indirection, and store the > variable-sized stuff elsewhere, reallocating storage when the amount > available is not big enough. It is quite difficult to get the indirect approach to work right. Think about renaming a subcomponent of the thing, or taking 'Access of a subcomponent. Then the thing moves elsewhere in the heap when it grows. Bad news! I've seen compiler bugs in this area. > As with most implementation decisions, it's a trade off among > complexity, space, and time. Indeed. - Bob ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Discriminated types with default discriminants 2005-11-03 23:08 ` Robert A Duff @ 2005-11-04 0:08 ` Adam Beneschan 2005-11-29 2:49 ` Randy Brukardt 0 siblings, 1 reply; 15+ messages in thread From: Adam Beneschan @ 2005-11-04 0:08 UTC (permalink / raw) Robert A Duff wrote: > > A few compilers will add a level of indirection, and store the > > variable-sized stuff elsewhere, reallocating storage when the amount > > available is not big enough. > > It is quite difficult to get the indirect approach to work right. > Think about renaming a subcomponent of the thing, Ummm ... isn't this exactly what's disallowed by 8.5.1(5)? -- Adam ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Discriminated types with default discriminants 2005-11-04 0:08 ` Adam Beneschan @ 2005-11-29 2:49 ` Randy Brukardt 2005-12-02 18:22 ` Robert A Duff 0 siblings, 1 reply; 15+ messages in thread From: Randy Brukardt @ 2005-11-29 2:49 UTC (permalink / raw) "Adam Beneschan" <adam@irvine.com> wrote in message news:1131062882.814405.147150@g44g2000cwa.googlegroups.com... > Robert A Duff wrote: > > > > A few compilers will add a level of indirection, and store the > > > variable-sized stuff elsewhere, reallocating storage when the amount > > > available is not big enough. > > > > It is quite difficult to get the indirect approach to work right. > > Think about renaming a subcomponent of the thing, > > Ummm ... isn't this exactly what's disallowed by 8.5.1(5)? Yes, it is. Bob is thinking about cases where a non-discriminant component is moved by the changing of a discriminant. (I know this because he and I have had this particular discussion repeatedly.) An implementation like that is bound to fail, IMHO. On the other hand, an implementation like Janus/Ada's (in which discriminant dependent components are just descriptors to the actual data) doesn't have this problem. (There is some complication determining the correct storage pool to use - think about a discriminant changing assignment on a subprogram parameter - but its not particularly hard to get right.) Randy. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Discriminated types with default discriminants 2005-11-29 2:49 ` Randy Brukardt @ 2005-12-02 18:22 ` Robert A Duff 0 siblings, 0 replies; 15+ messages in thread From: Robert A Duff @ 2005-12-02 18:22 UTC (permalink / raw) "Randy Brukardt" <randy@rrsoftware.com> writes: > "Adam Beneschan" <adam@irvine.com> wrote in message > news:1131062882.814405.147150@g44g2000cwa.googlegroups.com... > > Robert A Duff wrote: > > > > > > A few compilers will add a level of indirection, and store the > > > > variable-sized stuff elsewhere, reallocating storage when the amount > > > > available is not big enough. > > > > > > It is quite difficult to get the indirect approach to work right. > > > Think about renaming a subcomponent of the thing, > > > > Ummm ... isn't this exactly what's disallowed by 8.5.1(5)? > > Yes, it is. Bob is thinking about cases where a non-discriminant component > is moved by the changing of a discriminant. (I know this because he and I > have had this particular discussion repeatedly.) An implementation like that > is bound to fail, IMHO. On the other hand, an implementation like > Janus/Ada's (in which discriminant dependent components are just descriptors > to the actual data) doesn't have this problem. (There is some complication > determining the correct storage pool to use - think about a discriminant > changing assignment on a subprogram parameter - but its not particularly > hard to get right.) Thanks for replying, Randy. When I saw Adam's note, I then recalled that you and I had had the same discussion some years ago, and I think you pointed out the same paragraph. But by the time I got around to replying to Adam, I couldn't find his note. I may be confused on this issue. The bug in question was years ago, and was in an Ada 83 compiler (not Janus Ada -- as Randy explained above, it doesn't have this bug). I think Randy's description of what I was thinking of is correct. Something like this: type R(D: Natural := 0) is record S: String(1..D); Blah: Integer; end; X: R := (D => 4, S => "abcd", Blah => 5); Y: Integer renames X.Blah; X := (D => 5, S => "ABCDE", Blah => X.Blah); The compiler in question allocated the whole record R on the heap, so the stack variable X just contained an address. When X is assigned D=>5, it needs to grow, so the generated code would move the data and make X point to a different spot. But Y was implemented as the address of X.Blah, which moved, which made Y a dangling pointer. To fix this compiler bug, you would have to implement renaming differently, or else do it like Randy said above (make component S indirect, rather than the whole record R). Many compilers won't tolerate the above example at all -- they will try to allocate 2 billion bytes for X, and crash with Storage_Error. - Bob ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Discriminated types with default discriminants 2005-11-03 18:51 ` Jeffrey R. Carter 2005-11-03 23:08 ` Robert A Duff @ 2005-11-04 9:18 ` Maciej Sobczak 1 sibling, 0 replies; 15+ messages in thread From: Maciej Sobczak @ 2005-11-04 9:18 UTC (permalink / raw) Jeffrey R. Carter wrote: > Aside : begin > > When I see something like this, I always wonder: What does a negative > Size mean? > > To my mind, a negative Size is meaningless, and should not be allowed: > > Size : Natural > > end Aside; Sure - no need to worry. :) Just trying discriminated types: I picked Integer since the actual type would depend on the domain and without any particular domain (not even a homework) there was no reason to focus on type choices. > There are 3 cases with discriminants: > > 1. No default (object must be declared with explicit value) > 2. Default, and object declared with explicit value > 3. Default, and object declared without explicit value > > The 1st 2 cases are equivalent. The object must always have the same > value for the discriminant. It can never change. The object is constrained. > > The last case means the discriminant can change. The object is > unconstrained. *Now* it all makes sense. I understand that for that last case the default discriminant value is actually used (I got an impression that it's not used at all), but is not considered to be fixed nor limiting - this is what "unconstrained" means in this context. It is the discriminant's *type* that defines the range of sizes for the final object and that's why I got the warning about the possibility of getting storage error. This: subtype MyInt is Integer; type Discriminated(Size : MyInt := 10) is makes the warning go away (GNAT's "feature" - as explained by Dmitry), but does not change anything from the language point of view - the potential size of the object still depends on MyInt'Last and if the actual object is unconstrained, we get memory allocation problem due to the fact that GNAT chooses one particular way of managing memory for unconstrained objects. Thanks for the explanation. -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/ ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Discriminated types with default discriminants 2005-11-03 15:50 Discriminated types with default discriminants Maciej Sobczak ` (3 preceding siblings ...) 2005-11-03 18:51 ` Jeffrey R. Carter @ 2005-11-04 3:27 ` Brian May 2005-11-04 13:09 ` Stephen Leake 2005-11-04 17:58 ` Martin Krischik 4 siblings, 2 replies; 15+ messages in thread From: Brian May @ 2005-11-04 3:27 UTC (permalink / raw) >>>>> "Maciej" == Maciej Sobczak <no.spam@no.spam.com> writes: Hello, The 2nd warning has already been explained in detail, however I am still confused with the first warning: Maciej> Compiler (GNAT) gives me two warnings: Maciej> 5. Value : String (1..Size); Maciej> | >>>> warning: creation of object of this type may raise Maciej> Storage_Error Why does this warning go away when using an unbounded subtype? Doesn't the issue still exist? Maciej> I can get rid of the first warning with this: Maciej> subtype MyInt is Integer; Maciej> type Discriminated(Size : MyInt := 10) is Maciej> -- ... Thanks -- Brian May <bam@snoopy.apana.org.au> ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Discriminated types with default discriminants 2005-11-04 3:27 ` Brian May @ 2005-11-04 13:09 ` Stephen Leake 2005-11-04 17:58 ` Martin Krischik 1 sibling, 0 replies; 15+ messages in thread From: Stephen Leake @ 2005-11-04 13:09 UTC (permalink / raw) Brian May <bam@snoopy.apana.org.au> writes: >>>>>> "Maciej" == Maciej Sobczak <no.spam@no.spam.com> writes: > I am > still confused with the first warning: > > > Maciej> 5. Value : String (1..Size); > Maciej> | > >>>> warning: creation of object of this type may raise > Maciej> Storage_Error > > Why does this warning go away when using an unbounded subtype? Doesn't > the issue still exist? > > Maciej> I can get rid of the first warning with this: > > Maciej> subtype MyInt is Integer; > Maciej> type Discriminated(Size : MyInt := 10) is > Maciej> -- ... This is just a compiler bug. It assumes that since you specified a subtype, things are ok, and suppresses the warning. Note that 'warnings' are not defined by the language; they are provided by the compiler implementor in an attempt to make the compiler easier to use. You could report this to AdaCore (send an email to report@gnat.com); they typically take warning and error message issues seriously, since that is a good marketing point. -- -- Stephe ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Discriminated types with default discriminants 2005-11-04 3:27 ` Brian May 2005-11-04 13:09 ` Stephen Leake @ 2005-11-04 17:58 ` Martin Krischik 1 sibling, 0 replies; 15+ messages in thread From: Martin Krischik @ 2005-11-04 17:58 UTC (permalink / raw) Am 04.11.2005, 05:27 Uhr, schrieb Brian May <bam@snoopy.apana.org.au>: >>>>>> "Maciej" == Maciej Sobczak <no.spam@no.spam.com> writes: > > Hello, > > The 2nd warning has already been explained in detail, however I am > still confused with the first warning: > > Maciej> Compiler (GNAT) gives me two warnings: > > Maciej> 5. Value : String (1..Size); > Maciej> | > >>>> warning: creation of object of this type may raise > Maciej> Storage_Error > > Why does this warning go away when using an unbounded subtype? Doesn't > the issue still exist? Indeed it still exists - only the compiler did not detect it right away. Note: Warnings like this are usualy created by the optimizer and are not part of the language. > Maciej> I can get rid of the first warning with this: > > Maciej> subtype MyInt is Integer; > Maciej> type Discriminated(Size : MyInt := 10) is > Maciej> -- ... Martin ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2005-12-02 18:22 UTC | newest] Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2005-11-03 15:50 Discriminated types with default discriminants Maciej Sobczak 2005-11-03 16:06 ` Martin Krischik 2005-11-03 23:10 ` Robert A Duff 2005-11-04 5:01 ` Jeffrey R. Carter 2005-11-03 16:21 ` Ed Falis 2005-11-03 17:28 ` Dmitry A. Kazakov 2005-11-03 18:51 ` Jeffrey R. Carter 2005-11-03 23:08 ` Robert A Duff 2005-11-04 0:08 ` Adam Beneschan 2005-11-29 2:49 ` Randy Brukardt 2005-12-02 18:22 ` Robert A Duff 2005-11-04 9:18 ` Maciej Sobczak 2005-11-04 3:27 ` Brian May 2005-11-04 13:09 ` Stephen Leake 2005-11-04 17:58 ` Martin Krischik
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox