* private types @ 2006-03-13 19:58 ada_student 2006-03-13 20:27 ` Mark Lorenzen 2006-03-14 4:51 ` Jeffrey R. Carter 0 siblings, 2 replies; 91+ messages in thread From: ada_student @ 2006-03-13 19:58 UTC (permalink / raw) Consider the following package declaration, package PrivateType is type MyInteger is private; procedure Read(O : out myInteger); procedure Write(I : in MyInteger); private type MyInteger is range 1 .. 2**31 - 1; end; Why does Ada allow MyInteger to be made visible outside the scope of PrivateType ? Doesnt it make the code less secure(for example,consider an "uninitialized" object of type PrivateType.MyInteger). ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-13 19:58 private types ada_student @ 2006-03-13 20:27 ` Mark Lorenzen 2006-03-13 21:05 ` Pascal Obry 2006-03-13 21:07 ` ada_student 2006-03-14 4:51 ` Jeffrey R. Carter 1 sibling, 2 replies; 91+ messages in thread From: Mark Lorenzen @ 2006-03-13 20:27 UTC (permalink / raw) ada_student@yahoo.com writes: > Consider the following package declaration, > > package PrivateType is > > type MyInteger is private; > > procedure Read(O : out myInteger); > procedure Write(I : in MyInteger); > > private > > type MyInteger is range 1 .. 2**31 - 1; > > end; > > Why does Ada allow MyInteger to be made visible outside the > scope of PrivateType ? Doesnt it make the code less secure(for > example,consider an "uninitialized" object of type > PrivateType.MyInteger). First of all: If you want to learn about Ada, I can recommend the book "Programming in Ada 95" by John Barnes. I think that I understand what you are trying to do... You want to prevent the user of your package from declaring uninitialised variables of type PrivateType.MyInteger, right? In this case I would declare the partial view of the type (the non-private part) to be indefinite: type MyInteger (<>) is private; And then declare a function to provide an initial value of that type: function Nil returns MyInteger; The user of your package can then only declare a variable of type PrivateType.MyInteger if she initialises it at the same time: with PrivateType; [...] My_Var : PrivateType.MyInteger := PrivateType.Nil; Again: A good textbook on the subject will give you a much better understanding of the language than just trying to find Ada equivalents of C++ intricacies. - Mark ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-13 20:27 ` Mark Lorenzen @ 2006-03-13 21:05 ` Pascal Obry 2006-03-13 21:07 ` ada_student 1 sibling, 0 replies; 91+ messages in thread From: Pascal Obry @ 2006-03-13 21:05 UTC (permalink / raw) To: Mark Lorenzen Mark Lorenzen a �crit : > I think that I understand what you are trying to do... You want to > prevent the user of your package from declaring uninitialised > variables of type PrivateType.MyInteger, right? In this case I would > declare the partial view of the type (the non-private part) to be > indefinite: > > type MyInteger (<>) is private; Or: private type T is range 1 .. 2**31 - 1; type MyInteger is record Value : T := 0; end record; This depends on the "real" program. Hard to tell if this is not overkill for the simple code snippet posted :) Pascal. -- --|------------------------------------------------------ --| Pascal Obry Team-Ada Member --| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE --|------------------------------------------------------ --| http://www.obry.net --| "The best way to travel is by means of imagination" --| --| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595 ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-13 20:27 ` Mark Lorenzen 2006-03-13 21:05 ` Pascal Obry @ 2006-03-13 21:07 ` ada_student 2006-03-13 21:45 ` Simon Wright 1 sibling, 1 reply; 91+ messages in thread From: ada_student @ 2006-03-13 21:07 UTC (permalink / raw) > > type MyInteger (<>) is private; > Funny, how my copy of the AARM doesnt include this construct in the grammar although ObjectAda points to LRM:3.3.1(5) which states (in my copy) --> "An object_declaration without the reserved word constant declares a variable object. If it has a subtype_indication or an array_type_definition that defines an indefinite subtype, then there shall be an initialization expression. An initialization expression shall not be given if the object is of a limited type." ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-13 21:07 ` ada_student @ 2006-03-13 21:45 ` Simon Wright 0 siblings, 0 replies; 91+ messages in thread From: Simon Wright @ 2006-03-13 21:45 UTC (permalink / raw) ada_student@yahoo.com writes: >> >> type MyInteger (<>) is private; >> unknown_discriminant_part .. 3.7(3). This use is 7.3(11). ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-13 19:58 private types ada_student 2006-03-13 20:27 ` Mark Lorenzen @ 2006-03-14 4:51 ` Jeffrey R. Carter 2006-03-14 7:44 ` Brian May 1 sibling, 1 reply; 91+ messages in thread From: Jeffrey R. Carter @ 2006-03-14 4:51 UTC (permalink / raw) ada_student@yahoo.com wrote: > Consider the following package declaration, > > package PrivateType is > > type MyInteger is private; > > procedure Read(O : out myInteger); > procedure Write(I : in MyInteger); > > private > > type MyInteger is range 1 .. 2**31 - 1; > > end; > > Why does Ada allow MyInteger to be made visible outside the > scope of PrivateType ? Doesnt it make the code less secure(for > example,consider an "uninitialized" object of type > PrivateType.MyInteger). Because that's what private means in Ada. I suggest you spend some time with an Ada text or tutorial. It appears that you're guessing at Ada based on experience with another language. On-line texts and tutorials are available at adapower.com and adaworld.com. If you're fairly experienced in another language, you might want to look at "Ada Distilled". It's fairly concise while still providing a good introduction to Ada concepts. -- Jeff Carter "You've got the brain of a four-year-old boy, and I bet he was glad to get rid of it." Horse Feathers 47 ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-14 4:51 ` Jeffrey R. Carter @ 2006-03-14 7:44 ` Brian May 2006-03-14 8:25 ` Ludovic Brenta ` (2 more replies) 0 siblings, 3 replies; 91+ messages in thread From: Brian May @ 2006-03-14 7:44 UTC (permalink / raw) >>>>> "Jeffrey" == Jeffrey R Carter <spam.not.jrcarter@acm.not.spam.org> writes: >> MyInteger to be made visible outside the scope of PrivateType ? >> Doesnt it make the code less secure(for example,consider an >> "uninitialized" object of type PrivateType.MyInteger). Jeffrey> Because that's what private means in Ada. He does have a point though - some languages will initialise all variables to dummy values - this means you can get predictable results in code that (wrongly) uses them before setting them to a value. In this case it is possible to force initialisation (at least outside the package), as per another poster's suggestion, because it is a private type. Alternatively it is possible to turn it into a record type and provide a default value for the component, as per another post. In other cases it isn't so easy, e.g. any non-private non-record type. In fact, by default (at least last time I checked), gcc (or was that gnat) doesn't check the validity of parameters to functions if the type matches, even though the type hasn't been initialised and may just happen to contain an illegal value. I seem to recall Ada will initialise access types to null, and record components (if defaults given), but nothing else. -- Brian May <bam@snoopy.apana.org.au> ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-14 7:44 ` Brian May @ 2006-03-14 8:25 ` Ludovic Brenta 2006-03-14 8:47 ` Alex R. Mosteo 2006-03-17 4:33 ` Justin Gombos 2 siblings, 0 replies; 91+ messages in thread From: Ludovic Brenta @ 2006-03-14 8:25 UTC (permalink / raw) Brian May a écrit : > In fact, by default (at least last time I checked), gcc (or was that > gnat) doesn't check the validity of parameters to functions if the > type matches, even though the type hasn't been initialised and may > just happen to contain an illegal value. That is true, you need to pass -gnatVi -gnatVm to enable these checks. -- Ludovic Brenta. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-14 7:44 ` Brian May 2006-03-14 8:25 ` Ludovic Brenta @ 2006-03-14 8:47 ` Alex R. Mosteo 2006-03-17 4:33 ` Justin Gombos 2 siblings, 0 replies; 91+ messages in thread From: Alex R. Mosteo @ 2006-03-14 8:47 UTC (permalink / raw) Brian May wrote: >>>>>>"Jeffrey" == Jeffrey R Carter <spam.not.jrcarter@acm.not.spam.org> writes: > > >> MyInteger to be made visible outside the scope of PrivateType ? > >> Doesnt it make the code less secure(for example,consider an > >> "uninitialized" object of type PrivateType.MyInteger). > > Jeffrey> Because that's what private means in Ada. > > He does have a point though - some languages will initialise all > variables to dummy values - this means you can get predictable results > in code that (wrongly) uses them before setting them to a value. > > In this case it is possible to force initialisation (at least outside > the package), as per another poster's suggestion, because it is a > private type. Alternatively it is possible to turn it into a record > type and provide a default value for the component, as per another > post. > > In other cases it isn't so easy, e.g. any non-private non-record type. > > In fact, by default (at least last time I checked), gcc (or was that > gnat) doesn't check the validity of parameters to functions if the > type matches, even though the type hasn't been initialised and may > just happen to contain an illegal value. > > I seem to recall Ada will initialise access types to null, and record > components (if defaults given), but nothing else. Access variables are initialized to null by language definition. Normalize_Scalars pragma exists also, and Gnat has Initialize_Scalars I think. These can give more control, but IMHO that's an after-the-bug resort. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-14 7:44 ` Brian May 2006-03-14 8:25 ` Ludovic Brenta 2006-03-14 8:47 ` Alex R. Mosteo @ 2006-03-17 4:33 ` Justin Gombos 2006-03-17 5:17 ` Brian May ` (2 more replies) 2 siblings, 3 replies; 91+ messages in thread From: Justin Gombos @ 2006-03-17 4:33 UTC (permalink / raw) On 2006-03-14, Brian May <bam@snoopy.apana.org.au> wrote: > > He does have a point though - some languages will initialise all > variables to dummy values - this means you can get predictable > results in code that (wrongly) uses them before setting them to a > value. Beyond access types, I would not consider that feature you're describing helpful. In fact, it's more of a disservice. The first problem: initializing to zero, or some other "dummy" value of the compilers choice is likely to result in a valid value (sometimes), which only serves to /hide/ bugs in the cases where the object is used prior to a meaningful assignment. Then problem with user forced initialization (which is what the OP is after): it could mask the cases where reassignment is inevitable. IOW, suppose you have subprograms like this: function exists return boolean is --Later assignment to found_it is evitable -- found_it : boolean := false; begin if some_precondition then found_it := some_other_condition; end if; return found_it; end exists; In the above case, an initial value may persist if some path is not executed. The maintainer can immediately expect this to be the case upon seeing the initialization (assuming the author was competent). In other cases, an initial value may get overwritten no matter what. In these cases it makes more sense not to initialize, because it clarifies to the maintainer what kind of logic to expect before even looking at the body of code. It's always irritating to be reading someone elses code, and find that they've blanket initialized objects needlessly. It hides bugs, and also obscures the logic from the maintainer. We don't know enough about the OPs case to know whether forced initialization is wise, but he should be cautioned not to take this approach arbitrarily, or on a regular basis. It really depends on the situation. -- PM instructions: do a C4esar Ciph3r on my address; retain punctuation. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-17 4:33 ` Justin Gombos @ 2006-03-17 5:17 ` Brian May 2006-03-17 22:50 ` Justin Gombos 2006-03-18 1:17 ` Randy Brukardt 2006-03-17 7:40 ` Maciej Sobczak 2006-03-17 13:18 ` Robert A Duff 2 siblings, 2 replies; 91+ messages in thread From: Brian May @ 2006-03-17 5:17 UTC (permalink / raw) I am not sure how this: function exists return boolean is --Later assignment to found_it is evitable -- found_it : boolean := false; begin if some_precondition then found_it := some_other_condition; end if; return found_it; end exists; Is any better/worse then this: function exists return boolean is --Later assignment to found_it is evitable -- found_it : boolean; begin if some_precondition then found_it := some_other_condition; end if; return found_it; end exists; It is possible a smart compiler might trigger a warning in the second case - but this depends on you noticing the warning and investigating it. There are cases when the compiler might get confused and produce false positives or false negatives. Otherwise, the above problem is a problem that can only be found either by careful inspection of the code or by proper testing. For testing the code, as found_it is undefined in the second test, it is possible it might just fluke the tests you give it and pass everyone. The first code is predictable though, and as long as you give it the same inputs, it will always produce the same outputs, making it easier (IMHO) to test. -- Brian May <bam@snoopy.apana.org.au> ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-17 5:17 ` Brian May @ 2006-03-17 22:50 ` Justin Gombos 2006-03-18 1:17 ` Randy Brukardt 1 sibling, 0 replies; 91+ messages in thread From: Justin Gombos @ 2006-03-17 22:50 UTC (permalink / raw) On 2006-03-17, Brian May <bam@snoopy.apana.org.au> wrote: > I am not sure how this: > > function exists return boolean is > > --Later assignment to found_it is evitable > -- > found_it : boolean := false; > > begin > > if some_precondition then > > found_it := some_other_condition; > > end if; > > return found_it; > > end exists; > > Is any better/worse then this: > > function exists return boolean is > > --Later assignment to found_it is evitable > -- > found_it : boolean; > > begin > > if some_precondition then > > found_it := some_other_condition; > > end if; > > return found_it; > > end exists; The second case is obviously careless, and as you say, unpredictible. The first case is a good approach, as is this alternative: function exists return boolean is --Later assignment to found_it is inevitable -- found_it : boolean; begin if some_precondition then found_it := some_other_condition; else found_it := a_different_condition; end if; return found_it; end exists; My main purpose was to put the spotlight on this foolish practice: function exists return boolean is --Later assignment to found_it is inevitable -- found_it : boolean := false; --needless and misleading initialization begin if some_precondition then found_it := some_other_condition; else found_it := a_different_condition; end if; return found_it; end exists; Users of the OPs API might be forced into this scenario if the API is constructed to force explicit initialization on instantiation. > It is possible a smart compiler might trigger a warning in the > second case - but this depends on you noticing the warning and > investigating it. There are cases when the compiler might get > confused and produce false positives or false negatives. > > Otherwise, the above problem is a problem that can only be found > either by careful inspection of the code or by proper testing. Sure there are multiple opportunities to find flaws; but the idea is to not depend on them more than we have to. -- PM instructions: do a C4esar Ciph3r on my address; retain punctuation. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-17 5:17 ` Brian May 2006-03-17 22:50 ` Justin Gombos @ 2006-03-18 1:17 ` Randy Brukardt 2006-03-18 2:17 ` Justin Gombos ` (3 more replies) 1 sibling, 4 replies; 91+ messages in thread From: Randy Brukardt @ 2006-03-18 1:17 UTC (permalink / raw) "Brian May" <bam@snoopy.apana.org.au> wrote in message news:sa4hd5x1wgd.fsf@snoopy.microcomaustralia.com.au... ... > For testing the code, as found_it is undefined in the second test, it > is possible it might just fluke the tests you give it and pass > everyone. > > The first code is predictable though, and as long as you give it the > same inputs, it will always produce the same outputs, making it easier > (IMHO) to test. It's not just testing. Ada 95 is very clear that an Ada compiler cannot assume an object is in range unless it can prove it is initialized. Explicit initialization makes this proof trivial (and leaving it out may make it impossible to prove.) Thus, given A : Positive := 10; B : Positive; the compiler can assume that A is in range, potentially being able to eliminate checks and speeding up the code. But it cannot assume that B is in range (unless it can prove that it is initialized further on). So I recommend initalizing everything (or assigning it immediately after the begin) that could be significant to performance. Randy. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-18 1:17 ` Randy Brukardt @ 2006-03-18 2:17 ` Justin Gombos 2006-03-21 0:08 ` Randy Brukardt 2006-03-18 8:39 ` Uninitialized variables (was: Re: private types) Dirk Craeynest ` (2 subsequent siblings) 3 siblings, 1 reply; 91+ messages in thread From: Justin Gombos @ 2006-03-18 2:17 UTC (permalink / raw) On 2006-03-18, Randy Brukardt <randy@rrsoftware.com> wrote: > > Thus, given > A : Positive := 10; > B : Positive; > the compiler can assume that A is in range, potentially being able > to eliminate checks and speeding up the code. But it cannot assume > that B is in range (unless it can prove that it is initialized > further on). > > So I recommend initalizing everything (or assigning it immediately > after the begin) that could be significant to performance. As a rule, I try to put readability ahead of optimizations. But if I did want to write optimum code, I'm not seeing your point here. The runtime checks that might be placed on B need not affect code not handling B. Assuming an extreme case, suppose B is not assigned until 100 lines later (ie not immediately following the begin). There should be no runtime checks in those 100 lines between the 'begin' and the first assignment to B if B is not referenced (and if B is referenced prior to assignment, that's a problem that outweighs excessive checks anyway). The first occurrance of B is going to be an assignment to B, and it must have the same checks that A would have if A were being reassigned at this point. So I'm not seeing why more runtime checks would occur in the case of B. -- PM instructions: do a C4esar Ciph3r on my address; retain punctuation. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-18 2:17 ` Justin Gombos @ 2006-03-21 0:08 ` Randy Brukardt 0 siblings, 0 replies; 91+ messages in thread From: Randy Brukardt @ 2006-03-21 0:08 UTC (permalink / raw) "Justin Gombos" <rpbkbq.xax.gld@uluv.kbq> wrote in message news:I4KSf.552$bu.180@trnddc04... > On 2006-03-18, Randy Brukardt <randy@rrsoftware.com> wrote: > > > > Thus, given > > A : Positive := 10; > > B : Positive; > > the compiler can assume that A is in range, potentially being able > > to eliminate checks and speeding up the code. But it cannot assume > > that B is in range (unless it can prove that it is initialized > > further on). > > > > So I recommend initalizing everything (or assigning it immediately > > after the begin) that could be significant to performance. > > As a rule, I try to put readability ahead of optimizations. But if I > did want to write optimum code, I'm not seeing your point here. You're right about premature optimizations, of course. > The runtime checks that might be placed on B need not affect code not > handling B. Assuming an extreme case, suppose B is not assigned until > 100 lines later (ie not immediately following the begin). There > should be no runtime checks in those 100 lines between the 'begin' and > the first assignment to B if B is not referenced (and if B is > referenced prior to assignment, that's a problem that outweighs > excessive checks anyway). The first occurrance of B is going to be an > assignment to B, and it must have the same checks that A would have if > A were being reassigned at this point. So I'm not seeing why more > runtime checks would occur in the case of B. Because, in general, you don't know whether B is initialized. And Ada 95 requires that invalid values be detected before they cause any damage (with some unfortunate exceptions). If B is used to index an array, for instance, it must be checked unless the compiler can prove that it is valid. But that is very hard in general, because of path issues: B : Positive; begin if Bafflegab (10) then B := 10; end if; ... Str (B) ... -- Must check for invalid values here. end; There is no way that the compiler can tell if B has been initialized or not. And Ada 95 does not allow *assuming* that it is initialized (which is essentially what your argument boils down to) -- the compiler must presume the program is incorrect for this purpose unless it can prove that it is not. But note Bob Duff's point that there are other ways to arrange code generators that might have different effects on checking. That's true in general, but in this case in particular, the compiler cannot remove the check for Str (B) no matter what the code generation scheme. If B had been initialized, it would have been able to in most schemes. In any case, in most real code, it's hard to prove something is initialized unless it is done right at the top. Moreover, compilers vary in the amount of flow analysis that they do. So preinitializtion is the way to go for maximum portability. (But I suggest this when you're going to initialize the value anyway, as opposed to initializing it just for this purpose.) Randy. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Uninitialized variables (was: Re: private types) 2006-03-18 1:17 ` Randy Brukardt 2006-03-18 2:17 ` Justin Gombos @ 2006-03-18 8:39 ` Dirk Craeynest 2006-03-18 14:06 ` Gautier ` (2 more replies) 2006-03-18 12:06 ` private types Martin Dowie 2006-03-18 12:47 ` Robert A Duff 3 siblings, 3 replies; 91+ messages in thread From: Dirk Craeynest @ 2006-03-18 8:39 UTC (permalink / raw) [This thread really is about uninitialized variables now, so I changed the subject...] In article <e_mdncFXrsg5wobZnZ2dnUVZ_t2dnZ2d@megapath.net>, Randy Brukardt <randy@rrsoftware.com> wrote: >So I recommend initalizing everything (or assigning it immediately >after the begin) that could be significant to performance. We did (and do) feel this is not a good approach, at least not when using GNAT or another compiler that supports something like the pragma Initialize_Scalars and enhanced validity checking. For much more about uninitialized variables in Ada code, the following paper might be useful: "Exposing Uninitialized Variables: Strengthening and Extending Run-Time Checks in Ada" [1], Robert Dewar, Olivier Hainque, Dirk Craeynest, and Philippe Waroquiers, In "Proceedings of the 7th International Conference on Reliable Software Technologies - Ada-Europe 2002" [2], Vienna, Austria, June 17-21, 2002, Johan Blieberger and Alfred Strohmeier (Eds.), volume 2361 of Lecture Notes in Computer Science, pages 193-204, Springer-Verlag, 2002. The conclusion of that paper contains our recommendation: ---start-quote--- 5.3 Impact of Usage of Initialize Scalars on How to Program There is a trend in programming guidelines to "force" initializing everything at declaration resulting in code like: B : Natural := 0; if .... then B := 5; else B := 8; end if; The difficulty with such an approach is that the initial value is meaningless. If this value is used accidentally, the results are potentially just as wrong as the use of an uninitialized value, and furthermore, the explicit initialization precludes the approach we have described in this paper, and thus may introduce bugs that are much harder to find and fix. The automatic initialization under control of the compiler using Initialize Scalars is a far preferable approach. We therefore recommend that when a scalar is declared, the programmer should avoid initializing it if the code is supposed to set the value on all paths. It is better to let Initialize Scalars + gnatVa detect the bug in the code logic rather than trying to deal with meaningless initial values. Even for safety-critical programs, we can first compile with Initialize Scalars + gnatVa + invalid values and then, if needed, field the code with Initialize Scalars + all zero values (if it is the case that zero values give the code a better chance of avoiding seriously improper behavior). ---end-quote--- The GNAT manuals provide more information on GNAT's pragma Initialize_Scalars [3] and on enhanced validity checking [4]. Reference [3] mentions: ---start-quote--- Note that pragma Initialize_Scalars is particularly useful in conjunction with the enhanced validity checking that is now provided in GNAT, which checks for invalid values under more conditions. Using this feature (see description of the -gnatV flag in the users guide) in conjunction with pragma Initialize_Scalars provides a powerful new tool to assist in the detection of problems caused by uninitialized variables. ---end-quote--- We can assure everyone that from a developers and testers point of view the combination of Initialize_Scalars and enhanced validity checking is indeed "particularly useful". References: [1] <http://www.cs.kuleuven.be/~dirk/papers/ae02cfmu-paper.pdf> [2] <http://www.springer.de/cgi/svcat/search_book.pl?isbn=3-540-43784-3> [3] <http://www.adacore.com/wp-content/files/auto_update/gnat-unw-docs/html/gnat_rm_2.html#SEC48> [4] <http://www.adacore.com/wp-content/files/auto_update/gnat-unw-docs/html/gnat_ugn_4.html#SEC47> Dirk Dirk.Craeynest@cs.kuleuven.be (for Ada-Belgium/-Europe/SIGAda/WG9 mail) *** 11th Intl.Conf.on Reliable Software Technologies - Ada-Europe'2006 *** June 5-9, 2006 ** Porto, Portugal ** http://www.ada-europe.org *** ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized variables (was: Re: private types) 2006-03-18 8:39 ` Uninitialized variables (was: Re: private types) Dirk Craeynest @ 2006-03-18 14:06 ` Gautier 2006-03-18 14:36 ` Uninitialized variables Jeffrey Creem 2006-03-21 0:22 ` Uninitialized variables (was: Re: private types) Randy Brukardt 2006-03-21 0:38 ` Randy Brukardt 2 siblings, 1 reply; 91+ messages in thread From: Gautier @ 2006-03-18 14:06 UTC (permalink / raw) Here (trying to to sum up), 3 problems I see with the tactic of initializing everything: - useless initializations (i.e. dummy values rewritten later) take time and usually _hurt_ performance (think to number crunching with huge objects, or frequently used functions with local variables) - useless initializations introduce meaningless code lines - [Dirk] useless initializations prevent detecting bugs that can be detected without these initializations (they can be detected by combining the Initialize_Scalars pragma and the validity checks) My rule is rather to initialize _only_ variables you can give a meaningful values. Of course it depends on the context. Maybe there are situations where you can prefer a program giving wrong results than an unhandled exception popping at the wrong moment (although I find the method very shocking!)... In such cases the systematic initialization could be a way (not nice but pragmatic) to silently disable bug detection. _______________________________________________________________ Gautier -- http://www.mysunrise.ch/users/gdm/index.htm Ada programming -- http://www.mysunrise.ch/users/gdm/gsoft.htm NB: For a direct answer, e-mail address on the Web site! ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized variables 2006-03-18 14:06 ` Gautier @ 2006-03-18 14:36 ` Jeffrey Creem 0 siblings, 0 replies; 91+ messages in thread From: Jeffrey Creem @ 2006-03-18 14:36 UTC (permalink / raw) Gautier wrote: > Here (trying to to sum up), 3 problems I see with the tactic of > initializing everything: > > - useless initializations (i.e. dummy values rewritten later) take > time and usually _hurt_ performance (think to number crunching with > huge objects, or frequently used functions with local variables) > - useless initializations introduce meaningless code lines > - [Dirk] useless initializations prevent detecting bugs that can be > detected without these initializations (they can be detected by > combining the Initialize_Scalars pragma and the validity checks) > > My rule is rather to initialize _only_ variables you can give a > meaningful values. This is also the approach I follow. It has the added benefit that some compilers can now give you warnings about reading from it before you assign to it and thus help you find the bug. If one does the typical initialize everything to 0 or 'first or something like that then you can expect no help from the compiler. Now in reality, compilers vary in their ability to provide useful warnings in this area. GNAT does a reasonably good job of balancing real warnings in this case against false warnings. Another compiler I use takes a different approach where it seems to warn in a lot more cases and thus ends up with a lot more false positives. It is probably not that bad of an approach if you used this compiler from the beginning but with lots of lecagy code the signal to noise ratio of these warnings is so poor that I have not really found an effective way to make use of the warnings. Consider the following toy code: with Text_IO; procedure Toy is I : Integer; I_Set : Boolean := False; Should_We_Set_I : Character; J : Integer; begin Text_Io.Get(Should_We_Set_I); if Should_We_Set_I = 'y' then I_Set := True; I := 1; end if; if I_Set then Text_Io.Put_Line(Integer'Image(I)); -- This is ok Text_IO.Put_Line(Integer'image(J)); -- This is bad end if; J := 1; end Toy; GNAT Warns on the line that says This is bad but not on the line that says this is ok. Another compiler I use warns on both (Not posting other compiler here only because I have not tested this exact code on it and am making this assertion based on similar real code). Obviously, unless one uses someting like polyspace, a simple compiler can't be expected to detect all of these path flow type cases. The important point here is that if one had a convention that all variables should be initialized, no compiler could tell you that you were doing something wrong on the "this is bad line". ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized variables (was: Re: private types) 2006-03-18 8:39 ` Uninitialized variables (was: Re: private types) Dirk Craeynest 2006-03-18 14:06 ` Gautier @ 2006-03-21 0:22 ` Randy Brukardt 2006-03-21 0:38 ` Randy Brukardt 2 siblings, 0 replies; 91+ messages in thread From: Randy Brukardt @ 2006-03-21 0:22 UTC (permalink / raw) "Dirk Craeynest" <dirk@apollo.cs.kuleuven.ac.be> wrote in message news:dvgh0s$rtu$1@apollo.cs.kuleuven.ac.be... > [This thread really is about uninitialized variables now, so I changed > the subject...] > > In article <e_mdncFXrsg5wobZnZ2dnUVZ_t2dnZ2d@megapath.net>, > Randy Brukardt <randy@rrsoftware.com> wrote: > >So I recommend initalizing everything (or assigning it immediately > >after the begin) that could be significant to performance. > > We did (and do) feel this is not a good approach, at least not when > using GNAT or another compiler that supports something like the pragma > Initialize_Scalars and enhanced validity checking. > > For much more about uninitialized variables in Ada code, the following > paper might be useful: > > "Exposing Uninitialized Variables: Strengthening and Extending > Run-Time Checks in Ada" [1], > Robert Dewar, Olivier Hainque, Dirk Craeynest, and Philippe > Waroquiers, > In "Proceedings of the 7th International Conference on Reliable > Software Technologies - Ada-Europe 2002" [2], Vienna, Austria, > June 17-21, 2002, Johan Blieberger and Alfred Strohmeier (Eds.), > volume 2361 of Lecture Notes in Computer Science, pages 193-204, > Springer-Verlag, 2002. > > The conclusion of that paper contains our recommendation: > > ---start-quote--- > > 5.3 Impact of Usage of Initialize Scalars on How to Program > > There is a trend in programming guidelines to "force" initializing > everything at declaration resulting in code like: > > B : Natural := 0; > > if .... then > B := 5; > else > B := 8; > end if; > > The difficulty with such an approach is that the initial value is > meaningless. If this value is used accidentally, the results are > potentially just as wrong as the use of an uninitialized value, and > furthermore, the explicit initialization precludes the approach we > have described in this paper, and thus may introduce bugs that are much > harder to find and fix. The automatic initialization under control of > the compiler using Initialize Scalars is a far preferable approach. > > We therefore recommend that when a scalar is declared, the programmer > should avoid initializing it if the code is supposed to set the value > on all paths. It is better to let Initialize Scalars + gnatVa detect > the bug in the code logic rather than trying to deal with meaningless > initial values. Even for safety-critical programs, we can first compile > with Initialize Scalars + gnatVa + invalid values and then, if needed, > field the code with Initialize Scalars + all zero values (if it is the > case that zero values give the code a better chance of avoiding > seriously improper behavior). > > ---end-quote--- > > The GNAT manuals provide more information on GNAT's pragma > Initialize_Scalars [3] and on enhanced validity checking [4]. > Reference [3] mentions: > > ---start-quote--- > > Note that pragma Initialize_Scalars is particularly useful in > conjunction with the enhanced validity checking that is now provided > in GNAT, which checks for invalid values under more conditions. > Using this feature (see description of the -gnatV flag in the users > guide) in conjunction with pragma Initialize_Scalars provides a > powerful new tool to assist in the detection of problems caused by > uninitialized variables. > > ---end-quote--- > > We can assure everyone that from a developers and testers point of view > the combination of Initialize_Scalars and enhanced validity checking is > indeed "particularly useful". > > References: > [1] <http://www.cs.kuleuven.be/~dirk/papers/ae02cfmu-paper.pdf> > [2] <http://www.springer.de/cgi/svcat/search_book.pl?isbn=3-540-43784-3> > [3] <http://www.adacore.com/wp-content/files/auto_update/gnat-unw-docs/html/gnat _rm_2.html#SEC48> > [4] <http://www.adacore.com/wp-content/files/auto_update/gnat-unw-docs/html/gnat _ugn_4.html#SEC47> > > Dirk > Dirk.Craeynest@cs.kuleuven.be (for Ada-Belgium/-Europe/SIGAda/WG9 mail) > > *** 11th Intl.Conf.on Reliable Software Technologies - Ada-Europe'2006 > *** June 5-9, 2006 ** Porto, Portugal ** http://www.ada-europe.org *** ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized variables (was: Re: private types) 2006-03-18 8:39 ` Uninitialized variables (was: Re: private types) Dirk Craeynest 2006-03-18 14:06 ` Gautier 2006-03-21 0:22 ` Uninitialized variables (was: Re: private types) Randy Brukardt @ 2006-03-21 0:38 ` Randy Brukardt 2 siblings, 0 replies; 91+ messages in thread From: Randy Brukardt @ 2006-03-21 0:38 UTC (permalink / raw) "Dirk Craeynest" <dirk@apollo.cs.kuleuven.ac.be> wrote in message news:dvgh0s$rtu$1@apollo.cs.kuleuven.ac.be... > [This thread really is about uninitialized variables now, so I changed > the subject...] > > In article <e_mdncFXrsg5wobZnZ2dnUVZ_t2dnZ2d@megapath.net>, > Randy Brukardt <randy@rrsoftware.com> wrote: > >So I recommend initalizing everything (or assigning it immediately > >after the begin) that could be significant to performance. > > We did (and do) feel this is not a good approach, at least not when > using GNAT or another compiler that supports something like the pragma > Initialize_Scalars and enhanced validity checking. (followed by a number of quotes). I disagree in detail with your conclusions, but probably not in general. 1) Initialize_Scalars is an Annex H thing that is rarely available in Ada implementations. GNAT is the only one that I know of that has it. I don't think offering advice that most users can't follow is very helpful. 2) Initialized_Scalars does no good when you have full range types (which are very common in a compiler, for instance). In that case, it is equivalent to initializing to a random value, and worse, it gives a false sense of security. 3) "The initial value is meaningless". Here I agree and disagree with you. The agreement is that you shouldn't initialize to a meaningless value. The disagreement is that for most variables, there is an obvious initial value (like Null for access types) that is not meaningless. For instance, I have a lot of string processing code in the spam filter that have length variables. I usually initialize the length to zero (empty), because that *is* the initial state of the object. So, much of time there is a useful initialization. It think it is better to *avoid* uninitialized variables than to argue about how to *handle* uninitialized values. The example you gave: B : Natural := 0; if .... then B := 5; else B := 8; end if; is awful, I agree. But I'd probably write: B : Natural := 8; if .... then B := 5; -- else use the default values end if; instead, and the initial value is no longer meaningless. Similarly, I use a lot of blocks, and try to keep the declarations on variables to scopes where their initial values are known (or immediately initialized). Both of these are better than *any* technique to handle uninitialized variables. 4) As your note suggested, assuming that everything is tested is dangerous. It's necessary in the fielded system to protect against uninitialized variables causing weird results. I just prefer to do it from the beginning (by reducing them as much as possible). And I'd prefer to rely on compile-time warnings (which GNAT also does well, BTW) to get rid of them at the source. 5) Any extra cost from initializing objects to meaningful values early (and such cost is usually quite small) will quickly pay for itself. (I think that is in line with the conclusions of the paper, too). Conclusion: don't write uninitialized variables in the first place; but use your head to eliminate them - junk initializations are no better than the uninitialized variables that they replace. Mindless following of coding standards always produces junky code. Randy. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-18 1:17 ` Randy Brukardt 2006-03-18 2:17 ` Justin Gombos 2006-03-18 8:39 ` Uninitialized variables (was: Re: private types) Dirk Craeynest @ 2006-03-18 12:06 ` Martin Dowie 2006-03-18 12:47 ` Robert A Duff 3 siblings, 0 replies; 91+ messages in thread From: Martin Dowie @ 2006-03-18 12:06 UTC (permalink / raw) Randy Brukardt wrote: > It's not just testing. Ada 95 is very clear that an Ada compiler cannot > assume an object is in range unless it can prove it is initialized. Explicit > initialization makes this proof trivial (and leaving it out may make it > impossible to prove.) Thus, given > A : Positive := 10; > B : Positive; > the compiler can assume that A is in range, potentially being able to > eliminate checks and speeding up the code. But it cannot assume that B is in > range (unless it can prove that it is initialized further on). > > So I recommend initalizing everything (or assigning it immediately after the > begin) that could be significant to performance. Or use a tool like PolySpace, which is very good at spotting this sort of thing. (www.polyspace.com). Cheers -- Martin ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-18 1:17 ` Randy Brukardt ` (2 preceding siblings ...) 2006-03-18 12:06 ` private types Martin Dowie @ 2006-03-18 12:47 ` Robert A Duff 3 siblings, 0 replies; 91+ messages in thread From: Robert A Duff @ 2006-03-18 12:47 UTC (permalink / raw) "Randy Brukardt" <randy@rrsoftware.com> writes: > It's not just testing. Ada 95 is very clear that an Ada compiler cannot > assume an object is in range unless it can prove it is initialized. This is not quite true. What the compiler can prove depends on the compiler's code generation strategy. Example: type Index is range 1..10; type A is array(Index) of Character; X: Index; -- not initialized here procedure P(Y: Index) is begin ... end P; ... -- (*) might initialize X here P(X); Suppose the compiler cannot prove that the code marked "-- (*)" will initialize X. The compiler has a choice: It can do a range check at the call to P, and then assume inside the body of P that Y is in range (even though the value _might_ have come from an uninitialized variable). Or, the compiler can avoid the range check on the call to P, in which case it cannot assume that Y is in range. > So I recommend initalizing everything (or assigning it immediately after the > begin) that could be significant to performance. That also depends on the compiler. Many compilers can prove that a variable is initialized here: begin if ... then A := 3; else A := 4; end if; ... -- Here, we can presume A is in range. Adding "A := 0;" between "begin" and "if" would be overkill for such compilers. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-17 4:33 ` Justin Gombos 2006-03-17 5:17 ` Brian May @ 2006-03-17 7:40 ` Maciej Sobczak 2006-03-17 16:41 ` Frank J. Lhota 2006-03-17 23:36 ` Justin Gombos 2006-03-17 13:18 ` Robert A Duff 2 siblings, 2 replies; 91+ messages in thread From: Maciej Sobczak @ 2006-03-17 7:40 UTC (permalink / raw) Justin Gombos wrote: >>He does have a point though - some languages will initialise all >>variables to dummy values - this means you can get predictable >>results in code that (wrongly) uses them before setting them to a >>value. > > Beyond access types, I would not consider that feature you're > describing helpful. In fact, it's more of a disservice. So you have the whole pragma as such "disservice": http://www.adaic.org/standards/95aarm/html/AA-H-1.html > The first problem: initializing to zero, or some other "dummy" value > of the compilers choice is likely to result in a valid value > (sometimes), which only serves to /hide/ bugs in the cases where the > object is used prior to a meaningful assignment. Right. Then, why not minimize the scope of the object to the extent when it's never even visible before being initialized with the value that is meaningful in the given context? It's not always possible, of course, but in many (most?) cases programmers tend to put all variables at the beginning of some rather coarse-grained scope (for example, beginning of the procedure or function), and later wonder what is the "right" initial value for them. It's the misplacement of declaration that is a primary source of problems and this is what should be actually addressed. > Then problem with user forced initialization (which is what the OP is > after): it could mask the cases where reassignment is inevitable. > IOW, suppose you have subprograms like this: > > function exists return boolean is > > --Later assignment to found_it is evitable > -- > found_it : boolean := false; > > begin > > if some_precondition then > > found_it := some_other_condition; > > end if; > > return found_it; > > end exists; Single entry - single exit syndrome? :) -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/ ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-17 7:40 ` Maciej Sobczak @ 2006-03-17 16:41 ` Frank J. Lhota 2006-03-17 23:36 ` Justin Gombos 1 sibling, 0 replies; 91+ messages in thread From: Frank J. Lhota @ 2006-03-17 16:41 UTC (permalink / raw) Maciej Sobczak wrote: > Justin Gombos wrote: > >> .... >> >> Beyond access types, I would not consider that feature you're >> describing helpful. In fact, it's more of a disservice. > > So you have the whole pragma as such "disservice": > > http://www.adaic.org/standards/95aarm/html/AA-H-1.html Actually, the purpose of the Normalize_Scalars pragma is to eliminate any dependency on default initializations. The idea is to fill those scalars that are not initialized by the user with some extreme value, preferably out of range, so that any use of an uninitialized value can be readily detected. The Normalize_Scalars pragma is the high level version of the "DEAD BEEF" option provided by many Unix C compilers / linkers. As you may recall, the C standard specifies that any static data not initialized by the user is implicitly initialized to 0. With the "DEAD BEEF" option, the static data not initialized in the code is filled with the hex bytes 0xDEADBEEF, which results in outrageous integer / floating point / string values. Again, the point of this option is to eliminate dependence on implicit initialization. >> The first problem: initializing to zero, or some other "dummy" value >> of the compilers choice is likely to result in a valid value >> (sometimes), which only serves to /hide/ bugs in the cases where the >> object is used prior to a meaningful assignment. > > Right. Then, why not minimize the scope of the object to the extent when > it's never even visible before being initialized with the value that is > meaningful in the given context? It's not always possible, of course, > but in many (most?) cases programmers tend to put all variables at the > beginning of some rather coarse-grained scope (for example, beginning of > the procedure or function), and later wonder what is the "right" initial > value for them. It's the misplacement of declaration that is a primary > source of problems and this is what should be actually addressed. > >> Then problem with user forced initialization (which is what the OP is >> after): it could mask the cases where reassignment is inevitable. >> IOW, suppose you have subprograms like this: >> >> function exists return boolean is >> >> --Later assignment to found_it is evitable >> -- >> found_it : boolean := false; >> >> begin >> >> if some_precondition then >> >> found_it := some_other_condition; >> >> end if; >> >> return found_it; >> >> end exists; > > Single entry - single exit syndrome? :) > > -- "All things extant in this world, Gods of Heaven, gods of Earth, Let everything be as it should be; Thus shall it be!" - Magical chant from "Magical Shopping Arcade Abenobashi" "Drizzle, Drazzle, Drozzle, Drome, Time for the this one to come home!" - Mr. Lizard from "Tootor Turtle" ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-17 7:40 ` Maciej Sobczak 2006-03-17 16:41 ` Frank J. Lhota @ 2006-03-17 23:36 ` Justin Gombos 2006-03-18 1:32 ` Randy Brukardt 2006-03-18 9:20 ` private types Dmitry A. Kazakov 1 sibling, 2 replies; 91+ messages in thread From: Justin Gombos @ 2006-03-17 23:36 UTC (permalink / raw) On 2006-03-17, Maciej Sobczak <no.spam@no.spam.com> wrote: > > So you have the whole pragma as such "disservice": > > http://www.adaic.org/standards/95aarm/html/AA-H-1.html I don't have a problem with implicit initializations when the compiler can ensure a bad value (or "abnormal object", to use the language of the ARM). I was responding to Brian May's comment about compilers implicitly assigning "dummy values", which did not sound to me like values that are intelligently selected to be invalid for the type. I've heard of compilers implicitly initializing to zero, and figured that was what he might be advocating. BTW- I sometimes have a use for creating an abnormal object, and find Ada lacking in not providing such a mechanism. I'm sometimes forced to either include abnormal values in the set of values declared for a type, or to have a seperate flag. Both of these are messy. Why not have a 'invalid function added to Ada to enable simple and explicit initialization of abnormal objects? > Right. Then, why not minimize the scope of the object to the extent > when it's never even visible before being initialized with the value > that is meaningful in the given context? It's not always possible, > of course, but in many (most?) cases programmers tend to put all > variables at the beginning of some rather coarse-grained scope (for > example, beginning of the procedure or function), and later wonder > what is the "right" initial value for them. It's the misplacement of > declaration that is a primary source of problems and this is what > should be actually addressed. I agree. Declare blocks can eliminate some of these issues. I like the fact that declare blocks enable me to declare more constants than variables. But it's not a full solution. The opposite extreme of this would be to introduce a declare block at every introduction of a new object, which can obviously become detrimental to readability. It's a trade off that requires judgement - judgement that is unequal among adaists. > Single entry - single exit syndrome? :) Yes, I have that syndrome. I think I acquired it from the Ada Quality and Style Guide or a coding standard that I followed at one point. -- PM instructions: do a C4esar Ciph3r on my address; retain punctuation. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-17 23:36 ` Justin Gombos @ 2006-03-18 1:32 ` Randy Brukardt 2006-03-18 3:21 ` Handling invalid objects Justin Gombos 2006-03-18 9:20 ` private types Dmitry A. Kazakov 1 sibling, 1 reply; 91+ messages in thread From: Randy Brukardt @ 2006-03-18 1:32 UTC (permalink / raw) "Justin Gombos" <rpbkbq.xax.gld@uluv.kbq> wrote in message news:FJHSf.1898$TK2.497@trnddc07... ... > BTW- I sometimes have a use for creating an abnormal object, and find > Ada lacking in not providing such a mechanism. I'm sometimes > forced to either include abnormal values in the set of values > declared for a type, or to have a seperate flag. Both of these > are messy. Why not have a 'invalid function added to Ada to > enable simple and explicit initialization of abnormal objects? You're confusing an "invalid" object with an "abnormal" object. Accessing an abnormal one is erroneous; surely you don't want to intentionally put that into your programs. (Remember, "erroneous" is Ada-speak for "anything at all can happen".) The reason there is no way to construct invalid values is simple: there is no requirement that an implementation provide any such values. Some types (like Integer) don't have any invalid values; what would 'Invalid return for them. (This is the reason that Normalize_Scalars doesn't require initialization to invalid values.) Moreover, "invalid" only applies to scalar objects; there is no similar concept for composite types. In any case, this is a very complex area, and I don't think anyone wants to tread here. I'm dubious about your problem anyway; the values you are talking about are clearly part of the value set of a type. Claiming that they are not and trying to avoid including them is just confusing. "Null", for instance, is just another normal value (there are no valid or invalid values for access types, as they are not scalar) for an access type. Sure, it means "no object", and that's a bit unusual, but it's clearly an expected value. Randy. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Handling invalid objects 2006-03-18 1:32 ` Randy Brukardt @ 2006-03-18 3:21 ` Justin Gombos 2006-03-18 7:35 ` Jeffrey R. Carter ` (3 more replies) 0 siblings, 4 replies; 91+ messages in thread From: Justin Gombos @ 2006-03-18 3:21 UTC (permalink / raw) On 2006-03-18, Randy Brukardt <randy@rrsoftware.com> wrote: > > You're confusing an "invalid" object with an "abnormal" > object. Accessing an abnormal one is erroneous; surely you don't > want to intentionally put that into your programs. (Remember, > "erroneous" is Ada-speak for "anything at all can happen".) The 'Valid attribute exists to be able to handle abnormal objects. Here's a concrete example. Suppose I have: type clock_type is mod 12; function hour_of_day return clock_type; If hour_of_day gets called and for whatever reason I cannot return an hour_of_day, the caller needs to know that. Exceptions are a poor choice. The quality and style guide advises against them for a good reason; exceptions are like gotos - and produce a questionable state. It would be more graceful for me to return an invalid value (like -1), so my caller can simply do a 'Valid to discover whether the operation was successful. So what are the choices? 1) Declare it as: type clock_type is mod 13; and add special handling code every time you increment or decrement the value to what you've chosen to be invalid. 2) Wrap clock_type in a record, and include a validity flag. Or loosely pass a flag back. 3) The hacker approach probably resembles something like this: invalid_hour_of_day : constant integer := -1; return_data : clock_type; if cannot_get_valid_time then for return_data'address use invalid_hour_of_day'address return return_data; end if; 4) Raise an exception. Did I miss any? They're all pretty sloppy. The second choice is probably the best one. Approach 2 on steroids: I previously worked on a team that had a generic package called something like validated_object, where you would pass in a type and it would return a private type which was internally a record with a flag and your type. Then you would call the provided "valid" function to get the validity status, a set function to set the status, and you'd have to call another function to get at the data. It was kind of a hassle to have to repackage things whenever handling something that may be invalid. It nearly doubled the number of types we handled because every type would have the validated version, but it was at least a way to pass objects that may be invalid, and it was used uniformly throughout the project (as opposed to each developer picking from any of the other approaches). ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-18 3:21 ` Handling invalid objects Justin Gombos @ 2006-03-18 7:35 ` Jeffrey R. Carter 2006-03-18 16:10 ` Justin Gombos 2006-03-18 8:57 ` Jacob Sparre Andersen ` (2 subsequent siblings) 3 siblings, 1 reply; 91+ messages in thread From: Jeffrey R. Carter @ 2006-03-18 7:35 UTC (permalink / raw) Justin Gombos wrote: > > The 'Valid attribute exists to be able to handle abnormal objects. And it exists to handle results from outside normal Ada processing, such as values from hardware or from interfacing to other languages. There's a basic SW-engineering principle that one thing should have one meaning. Using one thing with 2 meanings, which is what you're asking for, clearly violates that principle. You'll find plenty of code, including some things in the standard Ada library, that violate this principle. Nevertheless, it is rarely a good idea to violate this principle. > type clock_type is mod 12; > > function hour_of_day return clock_type; This seems to specify a function that is expected to always be able to return a valid value. If it is expected to only be able to return a valid value some of the time, that should be documented, probably by naming the function something like Try_To_Get_Hour_Of_Day. If the function should always be able to return a valid value, and it can't, that is clearly an exceptional situation, and an exception is clearly the correct way to deal with such a situation. If valid values are not always possible, then it's a question of how often they are not available. If it's a fairly common occurrence (and that can be less than 50% of the time), then it's not an exceptional situation, and an unconstrained record type with a Boolean discriminant is probably the best thing to return. If, on the other hand, it's a rare occurrence, then it's still an exceptional situation, and an exception is the correct solution. Anyone who has seen C code that correctly checks and deals with all returned error codes and success flags knows how complicated and unreadable such code is. The common practice in C is to not do the necessary checks so that the code is simpler and more readable. That is clearly not an acceptable solution. Exceptions separate the normal processing from the exceptional processing, allowing simple and readable code for the normal case while ensuring that all checks are performed and dealt with. There are cases where exceptions are outlawed; most of them are not justified. Even if they were all justified, advocating a return to the mess that error codes create is not a viable option. -- Jeff Carter "The time has come to act, and act fast. I'm leaving." Blazing Saddles 36 ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-18 7:35 ` Jeffrey R. Carter @ 2006-03-18 16:10 ` Justin Gombos 2006-03-19 11:00 ` Simon Wright 2006-03-20 23:57 ` Randy Brukardt 0 siblings, 2 replies; 91+ messages in thread From: Justin Gombos @ 2006-03-18 16:10 UTC (permalink / raw) On 2006-03-18, Jeffrey R. Carter <spam.not.jrcarter@acm.not.spam.org> wrote: > > There's a basic SW-engineering principle that one thing should have > one meaning. Using one thing with 2 meanings, which is what you're > asking for, clearly violates that principle. That's a good point. Given that perspective, would you say the practice of using null access values to indicate whether the access value is useable violates this principle? >> type clock_type is mod 12; >> >> function hour_of_day return clock_type; > > This seems to specify a function that is expected to always be able > to return a valid value. Pretend that there are cases where the hour of day is unavailable. I chose an example using mod only because it has added complications when increasing the range of values to allow for an invalid object, and hour of day is simple. > If it is expected to only be able to return a valid value some of > the time, that should be documented, probably by naming the function > something like Try_To_Get_Hour_Of_Day. There's that principle of naming non-boolean functions nouns, since they return an object. Also, if an API is often queried for information that it cannot retrieve, and often this is normal operation, subprogram prefixes like "try_to_get_" seem lengthy. I would have to use some other means to indicate that the returned value may be unusable. > If the function should always be able to return a valid value, and > it can't, that is clearly an exceptional situation, and an exception > is clearly the correct way to deal with such a situation. I recall working to a coding standard that barred exception raising when other mechanisms for error detection are possible. It effectively banned exception raising altogether because you can always send an error notice by other means. Exceptions are synonymous with goto statements, with the additional effect of creating an unpredictable state so I didn't challenge the rule. Exception raising and handling is often viewed as writing code that will never execute. Predefined exceptions must be handled when there is an expectation they will be raised, but their usefullness stops there. Beyond that, it's like writing erroneous code on purpose. > If valid values are not always possible, then it's a question of how > often they are not available. If it's a fairly common occurrence > (and that can be less than 50% of the time), then it's not an > exceptional situation, and an unconstrained record type with a > Boolean discriminant is probably the best thing to return. If, on > the other hand, it's a rare occurrence, then it's still an > exceptional situation, and an exception is the correct solution. I try to avoid variant records, but this sounds like a good use for them. I'll have to try that. > Anyone who has seen C code that correctly checks and deals with all > returned error codes and success flags knows how complicated and > unreadable such code is. The common practice in C is to not do the > necessary checks so that the code is simpler and more readable. That > is clearly not an acceptable solution. Exceptions separate the > normal processing from the exceptional processing, allowing simple > and readable code for the normal case while ensuring that all checks > are performed and dealt with. > > There are cases where exceptions are outlawed; most of them are not > justified. Even if they were all justified, advocating a return to > the mess that error codes create is not a viable option. It's a mess regardless. Clearly Ada is deficient in this respect, as all languages seem to be. -- PM instructions: do a C4esar Ciph3r on my address; retain punctuation. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-18 16:10 ` Justin Gombos @ 2006-03-19 11:00 ` Simon Wright 2006-03-20 23:57 ` Randy Brukardt 1 sibling, 0 replies; 91+ messages in thread From: Simon Wright @ 2006-03-19 11:00 UTC (permalink / raw) Justin Gombos <rpbkbq.xax.gld@uluv.kbq> writes: > Exception raising and handling is often viewed as writing code that > will never execute. Predefined exceptions must be handled when > there is an expectation they will be raised, but their usefullness > stops there. Beyond that, it's like writing erroneous code on > purpose. Code that _should_ never execute, perhaps! Exceptions are for things that can't be handled locally because of lack of application knowledge. For example, how to handle a Socket_Error? And also, I think, for contract violation, where the contract can;t be enforced in the language. Now we can say 'not null access' but in Ada95 we can't. >> There are cases where exceptions are outlawed; most of them are not >> justified. Even if they were all justified, advocating a return to >> the mess that error codes create is not a viable option. > > It's a mess regardless. Clearly Ada is deficient in this respect, > as all languages seem to be. I think it's called living in the real world. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-18 16:10 ` Justin Gombos 2006-03-19 11:00 ` Simon Wright @ 2006-03-20 23:57 ` Randy Brukardt 2006-03-22 2:06 ` Justin Gombos 1 sibling, 1 reply; 91+ messages in thread From: Randy Brukardt @ 2006-03-20 23:57 UTC (permalink / raw) "Justin Gombos" <rpbkbq.xax.gld@uluv.kbq> wrote in message news:niWSf.1278$I7.339@trnddc03... ... > I recall working to a coding standard that barred exception raising > when other mechanisms for error detection are possible. It > effectively banned exception raising altogether because you can always > send an error notice by other means. Exceptions are synonymous with > goto statements, with the additional effect of creating an > unpredictable state so I didn't challenge the rule. You should have; such a coding standard is brain-damaged. Unless there is a total ban on exceptions (as in SPARK -- and I disagree with SPARK on that), there is no good reason to avoid exceptions. It's important that they not be overused - especially in situations where it is normal and expected that the failure occur (such as in a Find routine). But it's silly to avoid them, even in rare but expected situations (such as end-of-file). Indeed, my view is exceptions and exception handling were one of the primary leaps forward for Ada over its sibling languages Pascal and Modula. Using exceptions in cases like this allow the writer of the routine to be sure that the error is not ignored, causing cascading problems later - and ensure that the error is localized if it is made. > Exception raising and handling is often viewed as writing code that > will never execute. Predefined exceptions must be handled when there > is an expectation they will be raised, but their usefullness stops > there. Beyond that, it's like writing erroneous code on purpose. Yikes! I hope you never work for me! I think returning an invalid value on purpose is like writing erroneous code on purpose. That's because you're trusting the caller to do the right thing and check something; if you look at the typical C code, it's pretty clear that doesn't happen much. Exceptions let you put the error recovery code where it makes the most sense -- which is usually quite a long ways from wherever the error occurred. And it doesn't require any trust from the user of your abstraction. (Note that this still applies even when you are your own consumer - no one is perfect enough to remember to do things not indicated in the specification.) Randy. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-20 23:57 ` Randy Brukardt @ 2006-03-22 2:06 ` Justin Gombos 2006-03-22 5:23 ` tmoran 0 siblings, 1 reply; 91+ messages in thread From: Justin Gombos @ 2006-03-22 2:06 UTC (permalink / raw) On 2006-03-20, Randy Brukardt <randy@rrsoftware.com> wrote: > > You should have; such a coding standard is brain-damaged. Unless > there is a total ban on exceptions (as in SPARK -- and I disagree > with SPARK on that), there is no good reason to avoid > exceptions. You would avoid exceptions for the same reasons you might avoid using a goto statement. An exception is only a specific type of goto statement - and gotos are not exactly state of the art. > Indeed, my view is exceptions and exception handling were one of the > primary leaps forward for Ada over its sibling languages Pascal and > Modula. Using exceptions in cases like this allow the writer of the > routine to be sure that the error is not ignored, causing cascading > problems later - and ensure that the error is localized if it is > made. Quite the opposit. I see neglected potentially raisable exceptions routinely. They are particularly easy to ignore - and in fact often difficult for untrained users to even know they're using something that would raise an exception. This makes exceptions the worst kind of goto. You can command a jump without even providing a place to go. It is the alternatives that forces the user of an API to address problem cases. In the case of functions, wrapping return data in a varient record is not something that can be ignored. Ignoring an "out" object on a procedure requires cases of neglect to be deliberate. >> Exception raising and handling is often viewed as writing code that >> will never execute. Predefined exceptions must be handled when >> there is an expectation they will be raised, but their usefullness >> stops there. Beyond that, it's like writing erroneous code on >> purpose. > > Yikes! I hope you never work for me! Rightly so. Bringing me into a sloppy environment with undisciplined Ada programmers and a mess of spaghetti code could quickly create a tough environment - and a particularly hostile one if I'm also forced to do poor quality work myself. I would not be a team player in that case, and you should not hire me. > I think returning an invalid value on purpose is like writing > erroneous code on purpose. That's because you're trusting the caller > to do the right thing and check something; It's exceptions that require trust. In fact, you can ignore an exception accidentally. Return a known and documented bad value, or varient record, and the user must not incompetent to miss it. Well developed Adaists can pull off using exceptions conservatively (just like they can gotos), with minimal benefit. However, you also can't ignore the fact that most Ada developers are incompetent, and will write code that doesn't execute, create exceptions for situations that are not exceptional, and fail to handle exceptions. I've seen new developers use exceptions to handle normal operating conditions. And you can't get away with only letting the advanced users write exceptions, because their code will interface with that of a non-proficient programmer. There are too many gotchas to justify them in light of better alternatives. -- PM instructions: do a C4esar Ciph3r on my address; retain punctuation. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-22 2:06 ` Justin Gombos @ 2006-03-22 5:23 ` tmoran 2006-03-22 8:48 ` Dmitry A. Kazakov 0 siblings, 1 reply; 91+ messages in thread From: tmoran @ 2006-03-22 5:23 UTC (permalink / raw) > An exception is only a specific type of goto > statement - and gotos are not exactly state of the art. If it doesn't quack, doesn't waddle, and doesn't look like a duck, it's not a duck. An exception both looks and acts quite different from a goto. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-22 5:23 ` tmoran @ 2006-03-22 8:48 ` Dmitry A. Kazakov 2006-03-22 9:24 ` Maciej Sobczak 0 siblings, 1 reply; 91+ messages in thread From: Dmitry A. Kazakov @ 2006-03-22 8:48 UTC (permalink / raw) On Tue, 21 Mar 2006 23:23:10 -0600, tmoran@acm.org wrote: >> An exception is only a specific type of goto >> statement - and gotos are not exactly state of the art. > If it doesn't quack, doesn't waddle, and doesn't look like a duck, > it's not a duck. An exception both looks and acts quite different > from a goto. If exceptions are gotos, then return codes should be gotos with label variables! (:-)) Still exception contracts would greatly improve safety of Ada as a language. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-22 8:48 ` Dmitry A. Kazakov @ 2006-03-22 9:24 ` Maciej Sobczak 2006-03-22 11:05 ` Dmitry A. Kazakov 0 siblings, 1 reply; 91+ messages in thread From: Maciej Sobczak @ 2006-03-22 9:24 UTC (permalink / raw) Dmitry A. Kazakov wrote: > Still exception contracts would greatly improve safety of Ada as a > language. If by exception contracts you mean embedding the exception specification in the "signature" of the procedure/function, then it was already exercised by the Java community with rather disappointing effects. -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/ ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-22 9:24 ` Maciej Sobczak @ 2006-03-22 11:05 ` Dmitry A. Kazakov 2006-03-22 16:42 ` Maciej Sobczak 0 siblings, 1 reply; 91+ messages in thread From: Dmitry A. Kazakov @ 2006-03-22 11:05 UTC (permalink / raw) On Wed, 22 Mar 2006 10:24:10 +0100, Maciej Sobczak wrote: > Dmitry A. Kazakov wrote: > >> Still exception contracts would greatly improve safety of Ada as a >> language. > > If by exception contracts you mean embedding the exception specification > in the "signature" of the procedure/function, then it was already > exercised by the Java community with rather disappointing effects. If Java did it wrong, let's do it right in Ada. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-22 11:05 ` Dmitry A. Kazakov @ 2006-03-22 16:42 ` Maciej Sobczak 2006-03-22 18:06 ` Stefan Lucks 2006-03-23 13:20 ` Dmitry A. Kazakov 0 siblings, 2 replies; 91+ messages in thread From: Maciej Sobczak @ 2006-03-22 16:42 UTC (permalink / raw) Dmitry A. Kazakov wrote: >>If by exception contracts you mean embedding the exception specification >>in the "signature" of the procedure/function, then it was already >>exercised by the Java community with rather disappointing effects. > > If Java did it wrong, let's do it right in Ada. Do what exactly? This is important question. The problem with exception specifications is that they are self-contradictory: - We use exceptions when we want to *DECOUPLE* error reporting from error handling. We find it especially good in those situations, where error reporting site and error handling site are separated by more than one level of subroutine calls (otherwise returning error codes is good enough). - We embed contract information in subroutine signatures to *COUPLE* the caller with the callee with respect to what they provide to each other and what they expect from each other. Now, "coupling" and "decoupling" are hardly compatible. Let's see where it breaks in so-called practice. First, there is a cascading effect when someone on one end of the chain adds a new exception type. Just let's say that the project evolved and for example a database got involved in something that was previously managed with the use of files. There is a new DBError exception, possibly having some db-specific information encoded (you know, exceptions are real objects in some languages :) ). This error is not handled neither by the offending function nor anybody in the chain, but is supposed to be handled at some higher level. In this scheme, the poor programmer has to add the DBError type to the exception specification to *all* functions in the chain. And apart from being a maintenance horror, it might be just impossible because the functions on the road are already closed or just owned by someone else. The tempting "solution" is to shut up the exception to meet the specification which was already cast in stone. Just grep any bigger Java project for things like: catch (Throwable e) {} // <- empty block here! to see it at work. Java guys can at least try to fight this problem with inheritance. The exception need not be exactly of the specified type, but might be something derived from what was specified. So, the other temptation is to specify the exception type that is rather general (higher in the inheritance hierarchy) to ease the accommodation of new exception types. But the more general is the specification, the less useful it is with regard to enforcing anything. In the extreme, it does not enforce anything at all. (Note that Ada would not have this possibility, or it would need to allow for exception hierarchies.) Second, the problem is that the error reporting and handling might be stated as a contract not between immediate caller and callee, but between some entities that operate across some other entity. A C++ example could be: void myFun() { vector<MyType> array; // ... sort(array.begin(), array.end(), myComparator()); // ... } Above, the call chain is myFun->sort->myComparator, but the error handling and reporting is the business which is agreed between myFun and myComparator only. The sort algorithm was written long before myFun and myComparator and it (sort) does not care what it sorts and for whom. This means that sort should be completely transparent to the agreement that myFun and myComparator might have with regard to error reporting and handling. The solution might be to allow the compiler to synthesise the exception specs for sort automatically. But then, the specs would be just useless, because it would not enforce anything. The real problem is that languages based on simple subroutine calls are not appropriate for expressing these kind of relationships. Something fundamentally different would be needed to ensure that myFun handles exceptions from myComparator without involving sort in this process, but I don't see what that thing would look like. Anyway. The whole purpose of exceptions is to provide a kind of "out-of-band" channel which is *decoupled* from the main chain of subroutine calls. This "out-of-band" property is something that you either like (and/or accept) or not in the given project. Messing around with things like exception specifications is just swimming upstream - you cannot provide coupling into something that was *intended* to be "out-of-band" in the first place. Java guys failed with this exercise. C++ community dropped the idea altogether before failing (C++ never had compile-time enforcements of exceptions specs and today nobody's using them anyway). I don't see how Ada would do something like this without incurring effects described above or without fundamentally changing something in the way subroutines are used. But I'm looking forward to see your opinions on this (and maybe learn something about Ada culture? :) ). -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/ ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-22 16:42 ` Maciej Sobczak @ 2006-03-22 18:06 ` Stefan Lucks 2006-03-23 13:20 ` Dmitry A. Kazakov 1 sibling, 0 replies; 91+ messages in thread From: Stefan Lucks @ 2006-03-22 18:06 UTC (permalink / raw) On Wed, 22 Mar 2006, Maciej Sobczak wrote: > Dmitry A. Kazakov wrote: > > > If Java did it wrong, let's do it right in Ada. > > Do what exactly? This is important question. > The problem with exception specifications is that they are > self-contradictory: > > - We use exceptions when we want to *DECOUPLE* error reporting from > error handling. We find it especially good in those situations, where > error reporting site and error handling site are separated by more than > one level of subroutine calls (otherwise returning error codes is good > enough). > > - We embed contract information in subroutine signatures to *COUPLE* the > caller with the callee with respect to what they provide to each other > and what they expect from each other. > > Now, "coupling" and "decoupling" are hardly compatible. [...] > Ada would do something like this without incurring effects described > above or without fundamentally changing something in the way subroutines > are used. But I'm looking forward to see your opinions on this (and > maybe learn something about Ada culture? :) ). One thing Ada could reasonably do is to *enable* subroutines to *promise* to raise no exceptions, or only certain exceptions. (And, of course, to enable the compiler to verify if this promise is kept. This would, be a little bit similar to SPARK, which can prove the exception-freedom of subroutines.) Of couse, the implication is that the subroutine itself may only use (or rather "with" ;-) subroutines which make a similar promise, or have to handle all exceptions ("others"). As an example for a notation, sonsider the following subroutines which any freedom to raise and propagate exceptions deliberately: function "+"(A, B: T) return T; procedure Get (Item: out T); procedure Put (Item: T); The remaining source code is not Ada. (Or perhaps it is Ada 2015? :-) No Exceptions raised: function "+"(A, B: T) return T raise null; procedure Get (Item: out T) raise null; procedure Put (Item: T) raise null; Some Exceptions may be raised: function "+"(A, B: T) return T raise Constraint_Error, Program_Error; -- can raise or propagate Program_Error, but nothing else procedure Get (Item: out T) raise Ada.Text_IO.End_Error, Ada.Text_IO.Data_Error, Ada.Text_IO.Mode_Error, Ada.Text_IO.Layout_Error; -- can raise or propagate these four exception, none else Line_Failed : exception; procedure PutLine (Item: T) raise Ada.Text_IO.End_Error, Ada.Text_IO.Data_Error, Line_Failed; -- can raise or propagate these three exceptions none else procedure Put (Item: T) raise Ada.Text_IO.End_Error, Ada.Text_IO.Data_Error, package; -- can raise or propagate two exceptions from Ada.Text_IO -- and any exception defined in the current package I could also imagine a package to specify which errors might be raised or propagated in any of its subroutines. This would simplify notation. Consider the following almost-complete example for a package specification with Ada.Text_IO; package Some_Library raise Ada.Text_IO.End_Error, Ada.Text_IO.Data_Error, Ada.Text_IO.Mode_Error, Ada.Text_IO.Layout_Error, Constrained_Error, Program_Error, package; -- Any subroutine defined here may raise the four exceptons from -- Ada.Text_IO, the two exceptions Constrained_Error, Program_Error, -- from Standard, and the exception(s) defined in the package, namely -- Line_Failed. Line_Failed : exception; type T is private; function "+"(A, B: T) return T; procedure PutLine (Item: T); procedure Put (Item: T); private type T is ...; -- which type T wold you like? end Mod_Some; Further, when a subroutines X formal parameter is access-to-subroutine, then any exception raised by a subroutine given as an actual parameter need not be handled by X. This should be the caller's duty. -- Stefan Lucks Th. Informatik, Univ. Mannheim, 68131 Mannheim, Germany e-mail: lucks@th.informatik.uni-mannheim.de home: http://th.informatik.uni-mannheim.de/people/lucks/ ------ I love the taste of Cryptanalysis in the morning! ------ ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-22 16:42 ` Maciej Sobczak 2006-03-22 18:06 ` Stefan Lucks @ 2006-03-23 13:20 ` Dmitry A. Kazakov 1 sibling, 0 replies; 91+ messages in thread From: Dmitry A. Kazakov @ 2006-03-23 13:20 UTC (permalink / raw) On Wed, 22 Mar 2006 17:42:53 +0100, Maciej Sobczak wrote: > Dmitry A. Kazakov wrote: > >>>If by exception contracts you mean embedding the exception specification >>>in the "signature" of the procedure/function, then it was already >>>exercised by the Java community with rather disappointing effects. >> >> If Java did it wrong, let's do it right in Ada. > > Do what exactly? This is important question. Sure. > - We use exceptions when we want to *DECOUPLE* error reporting from > error handling. We find it especially good in those situations, where > error reporting site and error handling site are separated by more than > one level of subroutine calls (otherwise returning error codes is good > enough). Yes, though also see below. > - We embed contract information in subroutine signatures to *COUPLE* the > caller with the callee with respect to what they provide to each other > and what they expect from each other. No, we are decoupling using contracts. Instead of presenting any concrete caller, we do a contract. The callee is coupled only to its contract. It does not to any caller, because it hopes that any caller will respect the contract. > Now, "coupling" and "decoupling" are hardly compatible. Let's see where > it breaks in so-called practice. > > First, there is a cascading effect when someone on one end of the chain > adds a new exception type. Just let's say that the project evolved and > for example a database got involved in something that was previously > managed with the use of files. This is not specific to exceptions. It is "fragile class" design. You cannot add a new exception type [better to say a class of], this breaks the contract. You have to stay within the class. In Ada model, where exceptions are values, this means that the exception contracts should specify ranges of values [subtype] and a new exception [value] should be chosen from that range. It is doable. > Second, the problem is that the error reporting and handling might be > stated as a contract not between immediate caller and callee, but > between some entities that operate across some other entity. [...] > The real problem is that languages based on simple subroutine calls are > not appropriate for expressing these kind of relationships. Something > fundamentally different would be needed to ensure that myFun handles > exceptions from myComparator without involving sort in this process, but > I don't see what that thing would look like. I think it was Robert Duff, who proposed a nice solution for this. When you have some procedure composed out of another procedure, in this example, you pass it as a parameter, you could say something like: A raises this plus anything what B does. Because B has a defined subroutine type, its contract is statically known. One could also bind exceptions to types of primitive subprograms. For example: type File is tagged ...; subtype File_Error is File'Exception; -- The range of exceptions bound to File procedure Read (X : File) exception File_Error; type DB is new File with ...; DB_Error : File_Error := some sugar; -- Declares a new exception in the range procedure Read (X : DB); -- This is allowed to raise DB_Error > Anyway. The whole purpose of exceptions is to provide a kind of > "out-of-band" channel which is *decoupled* from the main chain of > subroutine calls. This is a control-flow view. But there is another, more general view. Exceptions allow us to weaken preconditions. Without exceptions, a real-valued sqrt should specify x >= 0.0 as a precondition. This is unacceptable when x is statically unknown. Exceptions relax the precondition and bring things back to static. The price is that you leave the realm of real numbers. You have to this way or another. Either you make it complex-valued or you say that the result is "Real or Constraint_Error." Who will deal with this result is the question for another day. But when exceptions are not contracted, then the gain of static preconditions gets lost. So in my view, Java's is undoubtedly right here. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-18 3:21 ` Handling invalid objects Justin Gombos 2006-03-18 7:35 ` Jeffrey R. Carter @ 2006-03-18 8:57 ` Jacob Sparre Andersen 2006-03-19 19:07 ` Dr. Adrian Wrigley 2006-03-19 22:06 ` Brian May 2006-03-20 23:44 ` Randy Brukardt 3 siblings, 1 reply; 91+ messages in thread From: Jacob Sparre Andersen @ 2006-03-18 8:57 UTC (permalink / raw) Justin Gombos wrote: > The 'Valid attribute exists to be able to handle abnormal objects. > > Here's a concrete example. Suppose I have: > > type clock_type is mod 12; > > function hour_of_day return clock_type; > > If hour_of_day gets called and for whatever reason I cannot return > an hour_of_day, the caller needs to know that. Exceptions are a > poor choice. The quality and style guide advises against them for a > good reason; exceptions are like gotos - and produce a questionable > state. It would be more graceful for me to return an invalid value > (like -1), so my caller can simply do a 'Valid to discover whether > the operation was successful. No. The way to do that is to have proper values for all the states you want to handle, i.e.: type Hours is mod 12; type Clock_Type (Is_Set : Boolean := False) is new record case Is_Set is when True => Time : Hours; when False => null; end case; end record; Greetings, Jacob -- ACRONYM: A Contrived Reduction Of Nomenclature Yielding Mnemonics ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-18 8:57 ` Jacob Sparre Andersen @ 2006-03-19 19:07 ` Dr. Adrian Wrigley 2006-03-20 15:25 ` Robert A Duff 0 siblings, 1 reply; 91+ messages in thread From: Dr. Adrian Wrigley @ 2006-03-19 19:07 UTC (permalink / raw) On Sat, 18 Mar 2006 09:57:24 +0100, Jacob Sparre Andersen wrote: > Justin Gombos wrote: > >> The 'Valid attribute exists to be able to handle abnormal objects. >> >> Here's a concrete example. Suppose I have: >> >> type clock_type is mod 12; >> >> function hour_of_day return clock_type; >> >> If hour_of_day gets called and for whatever reason I cannot return >> an hour_of_day, the caller needs to know that. Exceptions are a >> poor choice. The quality and style guide advises against them for a >> good reason; exceptions are like gotos - and produce a questionable >> state. It would be more graceful for me to return an invalid value >> (like -1), so my caller can simply do a 'Valid to discover whether >> the operation was successful. > > No. The way to do that is to have proper values for all the states > you want to handle, i.e.: > > type Hours is mod 12; > > type Clock_Type (Is_Set : Boolean := False) is new > record > case Is_Set is > when True => > Time : Hours; > when False => > null; > end case; > end record; This is exactly the way I would expect this problem would be solved. It's one of the reasons for variant records. But it is still a bit messy (more verbose, extra component in names). Writing a generic just for one type is even more verbose, but in some fields you have a lot of invalid data around! In my field of stock trading, time series often have holes, probably erroneous values, and other problems and discrepencies. Tracking bad data, while keeping the code simple would be nice! It'd be great if the language allowed me to set and propagate invalid values naturally! With floating point, a NaN is the obvious choice. When you see NaNs output by your code, you know some/all of the calculation didn't work out properly. With access types, null can sometimes be used this way. But a proper invalid value would be useful. With integers, it would seem very sensible to have a NaN as well. Why did floats get a NaN value, but integers didn't? Languages often try to give facilities that can map onto hardware efficiently. But hardware tries to give exactly what the languages need, but no more. I think this vicious circle has made innovation with invalid values hard, in spite of the usefulness in software design, as well as hardware and software integrity. Of course, back in the olden days, some machines (which?) had ECC hardware, which generated an exception when invalid data was fetched from memory, and programs could deliberately write invalid bit patterns. This could be exploited to catch bugs and keep bad data from corrupting execution. Nowadays, you can't do this because the invalid bit patterns don't propagate through VM and cache subsytems (even although caches and backing stores have their own ECC). VHDL, when modelling hardware logic has a comprehensive system for tracking invalid values. Often the invalid data is irrelevant to the operation and valid data prevails. Sometimes, invalid data propagates and dominates. Raising exceptions all over the place cannot be a complete substitute. Only by building in data validity into the core of the language and/or hardware can you get widespread adoption. IEEE Floating Point shows it can be useful, inexpensive and ubiquitious. Programming guidelines, generic validity wrappers and compiler options are a poor alternative. -- Adrian ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-19 19:07 ` Dr. Adrian Wrigley @ 2006-03-20 15:25 ` Robert A Duff 0 siblings, 0 replies; 91+ messages in thread From: Robert A Duff @ 2006-03-20 15:25 UTC (permalink / raw) "Dr. Adrian Wrigley" <amtw@linuxchip.demon.co.uk.uk.uk> writes: > It'd be great if the language allowed me to set and propagate > invalid values naturally! Well, it would be pretty inefficient if Booleans had an extra "invalid" value, with or without hardware support. Think about packed arrays of Boolean. Such a feature should be optional. Some languages do support such things with lighter syntax than the variant record somebody suggested earlier. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-18 3:21 ` Handling invalid objects Justin Gombos 2006-03-18 7:35 ` Jeffrey R. Carter 2006-03-18 8:57 ` Jacob Sparre Andersen @ 2006-03-19 22:06 ` Brian May 2006-03-20 21:17 ` Jeffrey R. Carter 2006-03-20 23:44 ` Randy Brukardt 3 siblings, 1 reply; 91+ messages in thread From: Brian May @ 2006-03-19 22:06 UTC (permalink / raw) >>>>> "Justin" == Justin Gombos <rpbkbq.xax.gld@uluv.kbq> writes: Justin> The 'Valid attribute exists to be able to handle abnormal Justin> objects. Justin> Here's a concrete example. Suppose I have: Justin> type clock_type is mod 12; Justin> function hour_of_day return clock_type; Justin> If hour_of_day gets called and for whatever reason I Justin> cannot return an hour_of_day, the caller needs to know Justin> that. Exceptions are a poor choice. The quality and Justin> style guide advises against them for a good reason; Justin> exceptions are like gotos - and produce a questionable Justin> state. It would be more graceful for me to return an Justin> invalid value (like -1), so my caller can simply do a Justin> 'Valid to discover whether the operation was successful. If you returned an invalid value, I would consider that a breach of the contract you established where you declare you only return a valid clock_type. This is similar to a problem I have seen when tutoring C++, students get stuck on the problem that looks something like this: item &find_item(...) { ... search for item ... if (found) { return item; } else { return ????; } } The ideal solution would be exceptions, but the students haven't been taught exceptions yet when conducting this exercise. Another solution would be to change the API to return a struct value, but students are told they cannot change the API. So students typically hard code it to return the first item, on the assumption that there is a first item. Either that, or simply omit the return statement, and ignore the compiler warning. Not good programming practise either way... -- Brian May <bam@snoopy.apana.org.au> ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-19 22:06 ` Brian May @ 2006-03-20 21:17 ` Jeffrey R. Carter 0 siblings, 0 replies; 91+ messages in thread From: Jeffrey R. Carter @ 2006-03-20 21:17 UTC (permalink / raw) Brian May wrote: > > item &find_item(...) { > > ... search for item ... > > if (found) { > return item; > } else { > return ????; > } > } > > The ideal solution would be exceptions, but the students haven't been > taught exceptions yet when conducting this exercise. No, exceptions are not ideal. Such a function may often be used in contexts where not finding a match is more common than finding one; the former case is not exceptional. Consider a program like grep. It applies a regular-expression-matching function to every line in a file. It's quite common for > 80% of the matches to fail; that is not an exceptional situation. Using an exception to indicate no match would be incorrect. Booch made this fundamental error in the regular expression matcher in his components book. > Another solution would be to change the API to return a struct value, > but students are told they cannot change the API. Then what the student has is an incorrect specification that cannot be implemented. -- Jeff Carter "From this day on, the official language of San Marcos will be Swedish." Bananas 28 ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-18 3:21 ` Handling invalid objects Justin Gombos ` (2 preceding siblings ...) 2006-03-19 22:06 ` Brian May @ 2006-03-20 23:44 ` Randy Brukardt 2006-03-22 1:27 ` Justin Gombos 3 siblings, 1 reply; 91+ messages in thread From: Randy Brukardt @ 2006-03-20 23:44 UTC (permalink / raw) "Justin Gombos" <rpbkbq.xax.gld@uluv.kbq> wrote in message news:41LSf.4126$TK2.1805@trnddc07... > On 2006-03-18, Randy Brukardt <randy@rrsoftware.com> wrote: > > > > You're confusing an "invalid" object with an "abnormal" > > object. Accessing an abnormal one is erroneous; surely you don't > > want to intentionally put that into your programs. (Remember, > > "erroneous" is Ada-speak for "anything at all can happen".) > > The 'Valid attribute exists to be able to handle abnormal objects. No, it exists to handle *invalid* objects. It has no effect on *abnormal* objects. Please be careful with your terminology here because using the *abnormal* the way you are is very confusing. I'm using the terminology defined in the Standard: see http://www.adaic.com/standards/05aarm/html/AA-13-9-1.html (or the similar section in the Ada 95 manual) to see the definitions of the terms. > Here's a concrete example. Suppose I have: Your example shows *invalid* values, not *abnormal* values. ... > Exceptions are a poor choice. No, I think they're the right choice here (presuming you are talking about clock failure or some other unusual event). > The quality and style guide advises against them for a good > reason; exceptions are like gotos - and produce a questionable state. The state isn't questionable in this case: you have no legitimate value to return, so anything you return is garbage. That means there isn't any state to corrupt. Randy. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Handling invalid objects 2006-03-20 23:44 ` Randy Brukardt @ 2006-03-22 1:27 ` Justin Gombos 0 siblings, 0 replies; 91+ messages in thread From: Justin Gombos @ 2006-03-22 1:27 UTC (permalink / raw) On 2006-03-20, Randy Brukardt <randy@rrsoftware.com> wrote: > >> The quality and style guide advises against them for a good reason; >> exceptions are like gotos - and produce a questionable state. > > The state isn't questionable in this case: you have no legitimate > value to return, so anything you return is garbage. That means there > isn't any state to corrupt. I didn't post an sample body for function hour_of_day return clock_type, so you don't have enough information to be able to conclude whether the state is corrupted. For all we know, hour_of_day is impure and modifies global data, and raises exceptions from multiple points. -- PM instructions: do a C4esar Ciph3r on my address; retain punctuation. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-17 23:36 ` Justin Gombos 2006-03-18 1:32 ` Randy Brukardt @ 2006-03-18 9:20 ` Dmitry A. Kazakov 1 sibling, 0 replies; 91+ messages in thread From: Dmitry A. Kazakov @ 2006-03-18 9:20 UTC (permalink / raw) On Fri, 17 Mar 2006 23:36:05 GMT, Justin Gombos wrote: > BTW- I sometimes have a use for creating an abnormal object, and find > Ada lacking in not providing such a mechanism. I'm sometimes > forced to either include abnormal values in the set of values > declared for a type, or to have a seperate flag. Both of these > are messy. Why not have a 'invalid function added to Ada to > enable simple and explicit initialization of abnormal objects? As Randy have pointed out, there is a great difference between faults and bugs. If we stay in the realm of correct programs, then the mechanism you are asking for is subtyping. One can exclude some values by putting a subtype constraint on the base type. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-17 4:33 ` Justin Gombos 2006-03-17 5:17 ` Brian May 2006-03-17 7:40 ` Maciej Sobczak @ 2006-03-17 13:18 ` Robert A Duff 2006-03-17 23:44 ` Justin Gombos 2 siblings, 1 reply; 91+ messages in thread From: Robert A Duff @ 2006-03-17 13:18 UTC (permalink / raw) Justin Gombos <rpbkbq.xax.gld@uluv.kbq> writes: > On 2006-03-14, Brian May <bam@snoopy.apana.org.au> wrote: > > > > He does have a point though - some languages will initialise all > > variables to dummy values - this means you can get predictable > > results in code that (wrongly) uses them before setting them to a > > value. > > Beyond access types, I would not consider that feature you're > describing helpful. I'm not sure what the right answer is, but surely all the arguments for and against dummy values apply equally to access types. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-17 13:18 ` Robert A Duff @ 2006-03-17 23:44 ` Justin Gombos 2006-03-18 9:24 ` Dmitry A. Kazakov 2006-03-18 12:56 ` Robert A Duff 0 siblings, 2 replies; 91+ messages in thread From: Justin Gombos @ 2006-03-17 23:44 UTC (permalink / raw) On 2006-03-17, Robert A Duff <bobduff@shell01.TheWorld.com> wrote: > Justin Gombos <rpbkbq.xax.gld@uluv.kbq> writes: > > I'm not sure what the right answer is, but surely all the arguments > for and against dummy values apply equally to access types. I don't agree with that. Null is a standard abnormal object for access types in all languages, and can never be taken for something valid. Null pointers are quickly detected, and easily understood. But with any other type, null (zero) is most likely a valid value. This is probably why the ARM states: The implicit initial value for an access subtype is the null value of the access type. But makes no such rule for other types. -- PM instructions: do a C4esar Ciph3r on my address; retain punctuation. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-17 23:44 ` Justin Gombos @ 2006-03-18 9:24 ` Dmitry A. Kazakov 2006-03-18 12:56 ` Robert A Duff 1 sibling, 0 replies; 91+ messages in thread From: Dmitry A. Kazakov @ 2006-03-18 9:24 UTC (permalink / raw) On Fri, 17 Mar 2006 23:44:08 GMT, Justin Gombos wrote: > On 2006-03-17, Robert A Duff <bobduff@shell01.TheWorld.com> wrote: >> Justin Gombos <rpbkbq.xax.gld@uluv.kbq> writes: >> >> I'm not sure what the right answer is, but surely all the arguments >> for and against dummy values apply equally to access types. > > I don't agree with that. Null is a standard abnormal object for > access types in all languages, and can never be taken for something > valid. No. Null is a legal access value. You can compare, copy, assign null pointers. You *can* dereference them! It is just so, that the effect of this operation would be Constraint_Error. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-17 23:44 ` Justin Gombos 2006-03-18 9:24 ` Dmitry A. Kazakov @ 2006-03-18 12:56 ` Robert A Duff 2006-03-18 15:06 ` Justin Gombos 1 sibling, 1 reply; 91+ messages in thread From: Robert A Duff @ 2006-03-18 12:56 UTC (permalink / raw) Justin Gombos <rpbkbq.xax.gld@uluv.kbq> writes: > On 2006-03-17, Robert A Duff <bobduff@shell01.TheWorld.com> wrote: > > Justin Gombos <rpbkbq.xax.gld@uluv.kbq> writes: > > > > I'm not sure what the right answer is, but surely all the arguments > > for and against dummy values apply equally to access types. > > I don't agree with that. Null is a standard abnormal object for > access types in all languages, and can never be taken for something > valid. Null is neither "abnormal" nor "invalid" in Ada. As for "all languages", some have a concept of "null" or "nil" or whatever that is the same in this regard. Some languages have no such concept. In Ada, if an object of an access type has no explicit initial value, you can't easily tell whether that means "null is a meaningful value for this variable, and that's the default I want" versus "this variable will be initialized to a meaningful (non-null) value later". This is exactly analogous to the case with integers -- if they were default-initialized to zero, you can't easily tell whether zero is intended as a meaningful initial value, versus later initialization to a meaningful value. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-18 12:56 ` Robert A Duff @ 2006-03-18 15:06 ` Justin Gombos 2006-03-19 9:35 ` Martin Krischik 2006-03-25 21:40 ` Robert A Duff 0 siblings, 2 replies; 91+ messages in thread From: Justin Gombos @ 2006-03-18 15:06 UTC (permalink / raw) On 2006-03-18, Robert A Duff <bobduff@shell01.TheWorld.com> wrote: > > In Ada, if an object of an access type has no explicit initial > value, you can't easily tell whether that means "null is a > meaningful value for this variable, and that's the default I want" > versus "this variable will be initialized to a meaningful (non-null) > value later". If you want to distinguish between the two possiblities, you could explicitly initialize your pointers to null in the first case, and not in the second. I rarely use access types, and I probably wouldn't do that myself simply because I find the distinction unimportant for access types. Regardless, I'm not going to give up the benefit of having this distinction on non-access scalars simply because my access type declarations don't have it. > This is exactly analogous to the case with integers -- if they were > default-initialized to zero, you can't easily tell whether zero is > intended as a meaningful initial value, versus later initialization > to a meaningful value. Integers, and other non-access scalars are different in this case because you cannot expect zero to have the same meaning. Zero has a universal meaning with access types, but it could be in range or out of range for any other type. The ARM selects access types specifically to get a default initialization of zero for this reason. -- PM instructions: do a C4esar Ciph3r on my address; retain punctuation. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-18 15:06 ` Justin Gombos @ 2006-03-19 9:35 ` Martin Krischik 2006-03-19 14:52 ` Peter C. Chapin ` (2 more replies) 2006-03-25 21:40 ` Robert A Duff 1 sibling, 3 replies; 91+ messages in thread From: Martin Krischik @ 2006-03-19 9:35 UTC (permalink / raw) Justin Gombos wrote: > Zero has a > universal meaning with access types, but it could be in range or out > of range for any other type. ï¿œThe ARM selects access types > specifically to get a default initialization of zero for this reason. Who says that Null := 16#0#? I could image a Hardware/CPU/OS where it would be better to define Null := 16#FFFF_FFFF_FFFF_FFFF#. For example an OS who's Virtual Memory Management System assign address 16#0# to be a valid address and to hold some important process data to which the process needs access. Of course programming C or C++ on such an OS could be quite challenging (Write to (void*)0 and you mess up your Proccess Information Descriptor). Martin -- mailto://krischik@users.sourceforge.net Ada programming at: http://ada.krischik.com ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-19 9:35 ` Martin Krischik @ 2006-03-19 14:52 ` Peter C. Chapin 2006-03-19 15:08 ` Björn Persson 2006-03-19 18:15 ` Robert A Duff 2006-03-19 19:27 ` Jeffrey R. Carter 2 siblings, 1 reply; 91+ messages in thread From: Peter C. Chapin @ 2006-03-19 14:52 UTC (permalink / raw) Martin Krischik <krischik@users.sourceforge.net> wrote in news:1259548.CMTukHGvVZ@linux1.krischik.com: > Of course programming C or C++ on such an OS could be quite > challenging (Write to (void*)0 and you mess up your Proccess > Information Descriptor). The C/C++ standard does not require NULL pointers to be represented by all zero bits either. The null pointer constant, (void*)0, might be translated into 0xFFFFFFFF or some other value. Peter ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-19 14:52 ` Peter C. Chapin @ 2006-03-19 15:08 ` Björn Persson 2006-03-19 16:34 ` Martin Krischik ` (2 more replies) 0 siblings, 3 replies; 91+ messages in thread From: Björn Persson @ 2006-03-19 15:08 UTC (permalink / raw) Peter C. Chapin wrote: > Martin Krischik <krischik@users.sourceforge.net> wrote in > news:1259548.CMTukHGvVZ@linux1.krischik.com: >>Of course programming C or C++ on such an OS could be quite >>challenging (Write to (void*)0 and you mess up your Proccess >>Information Descriptor). > > The C/C++ standard does not require NULL pointers to be represented by all > zero bits either. The null pointer constant, (void*)0, might be translated > into 0xFFFFFFFF or some other value. Well, does the standard require that (void*)0 == NULL? What if I wanted a pointer to address zero on this hypothetical OS? How would I get that if (void*)0 gets transformed to a non-zero NULL? -- Bj�rn Persson PGP key A88682FD omb jor ers @sv ge. r o.b n.p son eri nu ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-19 15:08 ` Björn Persson @ 2006-03-19 16:34 ` Martin Krischik 2006-03-20 9:57 ` Maciej Sobczak 2006-03-20 20:29 ` Simon Wright 2006-03-19 17:43 ` Larry Kilgallen 2006-03-19 22:11 ` Peter C. Chapin 2 siblings, 2 replies; 91+ messages in thread From: Martin Krischik @ 2006-03-19 16:34 UTC (permalink / raw) Bjï¿œrn Persson wrote: > Peter C. Chapin wrote: >> Martin Krischik <krischik@users.sourceforge.net> wrote in >> news:1259548.CMTukHGvVZ@linux1.krischik.com: >>>Of course programming C or C++ on such an OS could be quite >>>challenging (Write to (void*)0 and you mess up your Proccess >>>Information Descriptor). >> >> The C/C++ standard does not require NULL pointers to be represented by >> all zero bits either. The null pointer constant, (void*)0, might be >> translated into 0xFFFFFFFF or some other value. > > Well, does the standard require that (void*)0 == NULL? Before I learned C++ in deeps I thought the same. But then I read that the use of #define NULL is depreciated C++ and that one should use a simple 0 instead. > What if I wanted > a pointer to address zero on this hypothetical OS? That too is an interesting point. Actually dereference to (char*)0 is not forbidden - you will get the content of memory element 0x0. And when I did C work on systems without an MMU and the memory protection this was a serious problem. (char*)NULL would return data. Modern OS don't map the first memory page to the process so access will result in an error. But they only do that to ease up C/C++ development. There is no other reason. > How would I get that > if (void*)0 gets transformed to a non-zero NULL? Interesting question. Martin -- mailto://krischik@users.sourceforge.net Ada programming at: http://ada.krischik.com ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-19 16:34 ` Martin Krischik @ 2006-03-20 9:57 ` Maciej Sobczak 2006-03-20 10:58 ` Peter C. Chapin ` (3 more replies) 2006-03-20 20:29 ` Simon Wright 1 sibling, 4 replies; 91+ messages in thread From: Maciej Sobczak @ 2006-03-20 9:57 UTC (permalink / raw) Martin Krischik wrote: >>Well, does the standard require that (void*)0 == NULL? > > Before I learned C++ in deeps I thought the same. But then I read that the > use of #define NULL is depreciated C++ and that one should use a simple 0 > instead. Where did you read this? NULL is not depreciated. It's defined in the <cstddef> header to be a null-pointer constant, which is any integral const expression that evaluates to 0. Possible definition is: #define NULL 0 Note: the following is explicitly prohibited: #define NULL (void*)0 but still, (void*)0 == NULL will always evaluate to true, even if the internal representation of the null pointer is not zero. >>What if I wanted >>a pointer to address zero on this hypothetical OS? > > That too is an interesting point. Actually dereference to (char*)0 is not > forbidden - you will get the content of memory element 0x0. Not necessarily. It depends on what is the internal representation of the null pointer. One of the possible ways to *really* get at address 0x0 is to do reinterpret_cast or use a union with the same effect. Usual cast notation as the one above will not do. >>How would I get that >>if (void*)0 gets transformed to a non-zero NULL? > > Interesting question. The interesting question is why it might make any difference to you? The only thing that really matters is that the null pointer is distinct from any other valid pointer, in which case it's equivalent to Ada's null. If you need more knowledge than this, then either you are doing something wrong, or you work in the application domain where you really need an intimate knowledge of all the parts of the underlying platform - including your compiler - in which case your above worries are gone anyway. -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/ ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-20 9:57 ` Maciej Sobczak @ 2006-03-20 10:58 ` Peter C. Chapin 2006-03-20 11:19 ` Peter C. Chapin 2006-03-20 13:06 ` Maciej Sobczak 2006-03-20 15:19 ` Robert A Duff ` (2 subsequent siblings) 3 siblings, 2 replies; 91+ messages in thread From: Peter C. Chapin @ 2006-03-20 10:58 UTC (permalink / raw) Maciej Sobczak <no.spam@no.spam.com> wrote in news:dvlu9d$mg6$1@sunnews.cern.ch: > Where did you read this? > NULL is not depreciated. It's defined in the <cstddef> header to be a > null-pointer constant, which is any integral const expression that > evaluates to 0. Possible definition is: > > #define NULL 0 > > Note: the following is explicitly prohibited: > > #define NULL (void*)0 This defintion of NULL is not workable in C++. This is because C++ does not allow pointers to void to be put into other pointer types without a cast. If the above definition was used the following would be an error: int *p = NULL; Thus in C++, NULL must be defined as the literal "0". Note that this issue does not come up in C because C's type system is more permissive. Thus the (void*)0 is often used in C. Because "NULL" just expands to "0" in C++, code using NULL can at times be misleading. For example consider void f(int); void f(char *); f(NULL); // Ambiguous, could call either f(int) or f(char *). This is a surprising error. Other surprises come up when passing NULL to functions taking a variable number of arguments. Type checking is essentially turned off for the variable arguments and thus if integers and pointers have different representations or if the NULL pointer must be handled in a special way (not all bits zero), errors can occur printf("The address is: %p\n", NULL); In C++ this passes the integer zero to printf, not a pointer. The compiler can't understand that "0" is a null pointer constant in this context because it doesn't know what type the second argument to printf is supposed to be. For these reasons many C++ experts recommend using "0" explicitly to represent NULL pointers and not the symbol NULL. This makes the problems above more apparent in the source and thus more likely that the programmer will notice them. Peter ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-20 10:58 ` Peter C. Chapin @ 2006-03-20 11:19 ` Peter C. Chapin 2006-03-20 13:06 ` Maciej Sobczak 1 sibling, 0 replies; 91+ messages in thread From: Peter C. Chapin @ 2006-03-20 11:19 UTC (permalink / raw) "Peter C. Chapin" <pchapin@sover.net> wrote in news:Xns978C3CC16F9D7pchapinsovernet@198.186.192.137: > Maciej Sobczak <no.spam@no.spam.com> wrote in > news:dvlu9d$mg6$1@sunnews.cern.ch: > >> Note: the following is explicitly prohibited: Let me apologize for my last posting... I had read the above as "the following is explicitly *permitted*". I need to read a little more carefully in the future! Peter ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-20 10:58 ` Peter C. Chapin 2006-03-20 11:19 ` Peter C. Chapin @ 2006-03-20 13:06 ` Maciej Sobczak 1 sibling, 0 replies; 91+ messages in thread From: Maciej Sobczak @ 2006-03-20 13:06 UTC (permalink / raw) Peter C. Chapin wrote: >>Note: the following is explicitly prohibited: >> >>#define NULL (void*)0 > > This defintion of NULL is not workable in C++. Which we've already cleared. :) > Thus in C++, NULL must be defined as the literal "0". Not exactly. It can be anything that is an integral constant expression evalutating to zero. Thus, "0" is one obvious choice, but not any better than, say, "0L", "'\0'" or even "(125 - 5 * 5 * 5)". > Because "NULL" just expands to "0" in C++, code using NULL can at times > be misleading. For example consider > > void f(int); > void f(char *); > > f(NULL); // Ambiguous, could call either f(int) or f(char *). > > This is a surprising error. That's why one of the sweeties in the upcoming C++ standard is a new keyword nullptr, which will be useable only in those contexts where a pointer type is expected, so that: f(nullptr); will always choose the second overload from the above. > Other surprises come up when passing NULL to > functions taking a variable number of arguments. Such functions are FUBARed anyway. :) > For these reasons many C++ experts recommend using "0" explicitly to > represent NULL pointers and not the symbol NULL. This makes the problems > above more apparent in the source and thus more likely that the > programmer will notice them. On the other hand, for the human reader "NULL" is immediately associated with some special pointer value, not with not-at-all-special integer, so that the following: if (item != NULL) ... is also immediately recognized as a test against *existence* of some item (which also implies that item is a pointer), not as a test against item's integer value. In such contexts I use NULL. As you see, this subject has many faces. I invite you to comp.lang.c++.moderated to discuss them in more depth. -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/ ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-20 9:57 ` Maciej Sobczak 2006-03-20 10:58 ` Peter C. Chapin @ 2006-03-20 15:19 ` Robert A Duff 2006-03-20 16:47 ` James Dennett 2006-03-20 19:12 ` Martin Krischik 2006-03-20 19:32 ` Martin Krischik 3 siblings, 1 reply; 91+ messages in thread From: Robert A Duff @ 2006-03-20 15:19 UTC (permalink / raw) Maciej Sobczak <no.spam@no.spam.com> writes: > but still, (void*)0 == NULL will always evaluate to true, even if the > internal representation of the null pointer is not zero. Are you sure? Are you talking about C or C++ or both? Does (void*)x always return NULL if x is an appropriate-sized integer whose value is zero? That would require run-time overhead if NULL is not represented as all-zero-bits. On the other hand, it's pretty confusing if casting zero to (void*) is sometimes guaranteed to return NULL, and sometimes not, depending on whether the zero value is known at compile time. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-20 15:19 ` Robert A Duff @ 2006-03-20 16:47 ` James Dennett 0 siblings, 0 replies; 91+ messages in thread From: James Dennett @ 2006-03-20 16:47 UTC (permalink / raw) Robert A Duff wrote: > Maciej Sobczak <no.spam@no.spam.com> writes: > >> but still, (void*)0 == NULL will always evaluate to true, even if the >> internal representation of the null pointer is not zero. > > Are you sure? Are you talking about C or C++ or both? It's true for both, given the right interpretation of (void*)0. > Does (void*)x always return NULL if x is an appropriate-sized integer > whose value is zero? Not necessarily. But if x is a null pointer constant, which to C++ means an integral constant expression with value zero, then it will. (C also allows an ICE of zero cast to void*, so you have a NPC already.) > That would require run-time overhead if > NULL is not represented as all-zero-bits. Yes, but that's not required. You can get different behaviour from int i(0); void *p((void*)i); than from int const i(0); void *p((void*)i); because for C++ the latter i is a valid integral constant expression, while the former is not. > On the other hand, it's pretty confusing if casting zero to (void*) > is sometimes guaranteed to return NULL, and sometimes not, depending > on whether the zero value is known at compile time. Afraid so; generally C++ is arranged so that removing const, where legal, should not change the meaning of code -- but this is an exception, in theory at least. -- James ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-20 9:57 ` Maciej Sobczak 2006-03-20 10:58 ` Peter C. Chapin 2006-03-20 15:19 ` Robert A Duff @ 2006-03-20 19:12 ` Martin Krischik 2006-03-21 7:27 ` Maciej Sobczak 2006-03-20 19:32 ` Martin Krischik 3 siblings, 1 reply; 91+ messages in thread From: Martin Krischik @ 2006-03-20 19:12 UTC (permalink / raw) Maciej Sobczak wrote: > Where did you read this? > NULL is not depreciated. It's defined in the <cstddef> header to be a > null-pointer constant, which is any integral const expression that > evaluates to 0. Possible definition is: But that is only a C compatibility header, only there to provide compatibility C and one should avoid using them in pure C++? Martin -- mailto://krischik@users.sourceforge.net Ada programming at: http://ada.krischik.com ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-20 19:12 ` Martin Krischik @ 2006-03-21 7:27 ` Maciej Sobczak 0 siblings, 0 replies; 91+ messages in thread From: Maciej Sobczak @ 2006-03-21 7:27 UTC (permalink / raw) Martin Krischik wrote: >>NULL is not depreciated. It's defined in the <cstddef> header to be a >>null-pointer constant, which is any integral const expression that >>evaluates to 0. Possible definition is: > > But that is only a C compatibility header No, there is nothing like this in C++. The C library is part of C++ by explicit inclusion, not by compatibility. Consider, for example, general purpose functions, like rand() (this one declared in <cstdlib>). It does not make any sense to say that such functions are C-compatibility stuff only, because that would imply that it's not possible to do even such basic things in "pure" C++. C++ *contains* the C library. It uses different header names (for example, cstdlib instead of stdlib.h) and namespace std (so that you have std::rand, std::printf, etc.), but everything is there and everything is part of C++. Including NULL. -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/ ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-20 9:57 ` Maciej Sobczak ` (2 preceding siblings ...) 2006-03-20 19:12 ` Martin Krischik @ 2006-03-20 19:32 ` Martin Krischik 2006-03-21 7:41 ` Maciej Sobczak 3 siblings, 1 reply; 91+ messages in thread From: Martin Krischik @ 2006-03-20 19:32 UTC (permalink / raw) Maciej Sobczak wrote: > The interesting question is why it might make any difference to you? > The only thing that really matters is that the null pointer is distinct > from any other valid pointer, in which case it's equivalent to Ada's > null. For C++ I can - barely - see that but C is supposed to system programming language suitable for kernel and/or embedded progamming. Taking that into account: How actually are the languages implementers to implement "distinct from any other valid pointer". If you are implementing a Ring 0 device driver on x86 all pointers are valid and on PC architecture there is memory at (void*0) which one might want to access. Martin -- mailto://krischik@users.sourceforge.net Ada programming at: http://ada.krischik.com ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-20 19:32 ` Martin Krischik @ 2006-03-21 7:41 ` Maciej Sobczak 0 siblings, 0 replies; 91+ messages in thread From: Maciej Sobczak @ 2006-03-21 7:41 UTC (permalink / raw) Martin Krischik wrote: >>The interesting question is why it might make any difference to you? >>The only thing that really matters is that the null pointer is distinct >>from any other valid pointer, in which case it's equivalent to Ada's >>null. > > For C++ I can - barely - see that but C is supposed to system programming > language suitable for kernel and/or embedded progamming. Taking that into > account: How actually are the languages implementers to implement > "distinct from any other valid pointer". Any way they want. > If you are implementing a Ring 0 > device driver on x86 all pointers are valid and on PC architecture there is > memory at (void*0) which one might want to access. The point is that if you are writing software for some specific piece of hardware, then handling of NULL is the least of your problems. You need extensive knowledge and guarantees, considering, among others, stuff like word sizes, alignment, byte ordering, representation and existence of trap values, etc. In other words, you don't just pick any compiler at random, but rather you use the one which gives you the set of required guarantees. And among those guarantees there will be something about the NULL pointer. Most likely you will just know that the NULL pointer has representation of all bits zero. Note also that in so called reality compilers that do not implement NULL as zero just do not sell very well. This is because many C programmers are used to do this: struct S { int x; char *p; /* ... */ }; struct S s; memset(&s, 0, sizeof(S)); /* <- here */ and later expect that s.p == NULL; The "idiom" of memsetting structures is so deeply rooted in the C community that you can find it in almost every C program and most C books. It's clear that the "idiom" bypasses the typesafety of fields by just plowing over their underlying representation, and this can work only with those compilers that do not exercise the full freedom that the standard gives them. So - no worry. It just works. :) -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/ ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-19 16:34 ` Martin Krischik 2006-03-20 9:57 ` Maciej Sobczak @ 2006-03-20 20:29 ` Simon Wright 1 sibling, 0 replies; 91+ messages in thread From: Simon Wright @ 2006-03-20 20:29 UTC (permalink / raw) Martin Krischik <krischik@users.sourceforge.net> writes: > Before I learned C++ in deeps I thought the same. But then I read > that the use of #define NULL is depreciated C++ and that one should > use a simple 0 instead. deprecated (depreciation is what happens to a currency during inflation) ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-19 15:08 ` Björn Persson 2006-03-19 16:34 ` Martin Krischik @ 2006-03-19 17:43 ` Larry Kilgallen 2006-03-19 22:11 ` Peter C. Chapin 2 siblings, 0 replies; 91+ messages in thread From: Larry Kilgallen @ 2006-03-19 17:43 UTC (permalink / raw) In article <1172812.9zPbPKbdVq@linux1.krischik.com>, Martin Krischik <krischik@users.sourceforge.net> writes: > Modern OS don't map the first memory page to the process so access will > result in an error. But they only do that to ease up C/C++ development. > There is no other reason. Some operating systems map the first memory page to the process to aid LISP development. Pity the person whose program uses both languages. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-19 15:08 ` Björn Persson 2006-03-19 16:34 ` Martin Krischik 2006-03-19 17:43 ` Larry Kilgallen @ 2006-03-19 22:11 ` Peter C. Chapin 2 siblings, 0 replies; 91+ messages in thread From: Peter C. Chapin @ 2006-03-19 22:11 UTC (permalink / raw) [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain, Size: 568 bytes --] Bj�rn Persson <spam-away@nowhere.nil> wrote in news:SteTf.48935$d5.205176@newsb.telia.net: > Well, does the standard require that (void*)0 == NULL? What if I > wanted a pointer to address zero on this hypothetical OS? How would I > get that if (void*)0 gets transformed to a non-zero NULL? I'd have to review the precise definition of the null pointer constant. Anything other than that is treated in the "usual" way. So for example, this might work const int p = 0; ... (void*)p ... Or maybe you need to take the 'const' off the declaration of p. Peter ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-19 9:35 ` Martin Krischik 2006-03-19 14:52 ` Peter C. Chapin @ 2006-03-19 18:15 ` Robert A Duff 2006-03-19 19:20 ` Martin Krischik 2006-03-19 19:27 ` Jeffrey R. Carter 2 siblings, 1 reply; 91+ messages in thread From: Robert A Duff @ 2006-03-19 18:15 UTC (permalink / raw) Martin Krischik <krischik@users.sourceforge.net> writes: > Justin Gombos wrote: > > > Zero has a > > universal meaning with access types, but it could be in range or out > > of range for any other type. ï¿œThe ARM selects access types > > specifically to get a default initialization of zero for this reason. > > Who says that Null := 16#0#? I could image a Hardware/CPU/OS where it would > be better to define Null := 16#FFFF_FFFF_FFFF_FFFF#. The convention on TOPS-20 for null (in all the various languages that have it) is to use some address other than zero. I don't remember which address. The OS protects that page so it traps (just as most modern operating systems do for page zero). There was even an Ada compiler for TOPS-20, and of course it obeyed that convention. Using all-zero-bits for null has some minor efficiency advantages. > For example an OS who's Virtual Memory Management System assign address > 16#0# to be a valid address and to hold some important process data to > which the process needs access. > > Of course programming C or C++ on such an OS could be quite challenging > (Write to (void*)0 and you mess up your Proccess Information Descriptor). I believe the C++ rule is that 0 (written in your program) is the same thing as NULL -- but it need not be represented internally by all-zero-bits. Casting the integer zero to a pointer, however, does not necessarily result in NULL. That's sort of confusing, but if you understand the rules, the "quite challenging" comment above does not hold. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-19 18:15 ` Robert A Duff @ 2006-03-19 19:20 ` Martin Krischik 2006-03-19 20:43 ` Dr. Adrian Wrigley 2006-03-20 9:40 ` Maciej Sobczak 0 siblings, 2 replies; 91+ messages in thread From: Martin Krischik @ 2006-03-19 19:20 UTC (permalink / raw) Robert A Duff wrote: > I believe the C++ rule is that 0 (written in your program) is the same > thing as NULL -- but it need not be represented internally by > all-zero-bits. ï¿œCasting the integer zero to a pointer, however, > does not necessarily result in NULL. ï¿œThat's sort of confusing, > but if you understand the rules, the "quite challenging" comment > above does not hold. Super! And how many (in %) of C++ programmer actually know that. By guess is 0.1%. And indeed I is the main problem: Only a very few C/C++ programmers actually master the language. Martin -- mailto://krischik@users.sourceforge.net Ada programming at: http://ada.krischik.com ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-19 19:20 ` Martin Krischik @ 2006-03-19 20:43 ` Dr. Adrian Wrigley 2006-03-20 15:01 ` Robert A Duff 2006-03-27 4:07 ` Dave Thompson 2006-03-20 9:40 ` Maciej Sobczak 1 sibling, 2 replies; 91+ messages in thread From: Dr. Adrian Wrigley @ 2006-03-19 20:43 UTC (permalink / raw) On Sun, 19 Mar 2006 20:20:52 +0100, Martin Krischik wrote: > Robert A Duff wrote: > >> I believe the C++ rule is that 0 (written in your program) is the same >> thing as NULL -- but it need not be represented internally by >> all-zero-bits. �Casting the integer zero to a pointer, however, >> does not necessarily result in NULL. �That's sort of confusing, >> but if you understand the rules, the "quite challenging" comment >> above does not hold. > > Super! And how many (in %) of C++ programmer actually know that. By guess is > 0.1%. And indeed I is the main problem: Only a very few C/C++ programmers > actually master the language. It is (or was) quite a common interview question, to see if C (and C++) programmers know their subject properly. As you say, Robert, most don't. A related topic is the issue of pointer representation, which (IIRC) says that pointers to char (any kind) and void have to be the same. Pointers to functions have to be the same. But all other pointers can have their own representation. All pointers can be converted to and from pointers to void, without loss. And pointers can have different sizes and different patterns for the null pointer. I suspect a lot of code would fail if compilers wanted to exercise their full freedoms! -- Adrian ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-19 20:43 ` Dr. Adrian Wrigley @ 2006-03-20 15:01 ` Robert A Duff 2006-03-27 4:07 ` Dave Thompson 1 sibling, 0 replies; 91+ messages in thread From: Robert A Duff @ 2006-03-20 15:01 UTC (permalink / raw) "Dr. Adrian Wrigley" <amtw@linuxchip.demon.co.uk.uk.uk> writes: > On Sun, 19 Mar 2006 20:20:52 +0100, Martin Krischik wrote: > > > Robert A Duff wrote: > > > >> I believe the C++ rule is that 0 (written in your program) is the same > >> thing as NULL -- but it need not be represented internally by > >> all-zero-bits. �Casting the integer zero to a pointer, however, > >> does not necessarily result in NULL. �That's sort of confusing, > >> but if you understand the rules, the "quite challenging" comment > >> above does not hold. > > > > Super! And how many (in %) of C++ programmer actually know that. By guess is > > 0.1%. And indeed I is the main problem: Only a very few C/C++ programmers > > actually master the language. > > It is (or was) quite a common interview question, to see if > C (and C++) programmers know their subject properly. As you > say, Robert, most don't. Martin said that. I have no idea how close his .1% estimate is to the truth. It's certainly true that many programmers learn their programming languages by experiment -- what works is all-too-often assumed to be what the language is. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-19 20:43 ` Dr. Adrian Wrigley 2006-03-20 15:01 ` Robert A Duff @ 2006-03-27 4:07 ` Dave Thompson 1 sibling, 0 replies; 91+ messages in thread From: Dave Thompson @ 2006-03-27 4:07 UTC (permalink / raw) -- On Sun, 19 Mar 2006 20:43:42 GMT, "Dr. Adrian Wrigley" <amtw@linuxchip.demon.co.uk.uk.uk> wrote: > On Sun, 19 Mar 2006 20:20:52 +0100, Martin Krischik wrote: (C++ null pointers not all-bits-zero, also true of C) > > Super! And how many (in %) of C++ programmer actually know that. By guess is > > 0.1%. And indeed I is the main problem: Only a very few C/C++ programmers > > actually master the language. > Languages, or either language. C++ is not C much as Ada is not Pascal. > It is (or was) quite a common interview question, to see if > C (and C++) programmers know their subject properly. As you > say, Robert, most don't. > I don't know how common it is on interviews, having neither attended nor given any for quite some time. It is several FAQs on comp.lang.c. > A related topic is the issue of pointer representation, which > (IIRC) says that pointers to char (any kind) and void have to be > the same. Pointers to functions have to be the same. But all Pointers to char and void the same, yes. Separately pointers to all structs, and to all unions; this allows using them for 'incomplete' types, almost (not fully) like Ada private. Pointers to functions, not completely. Pointers to differently prototyped functions are different types, and calling a function through a wrong-type pointer is Undefined Behavior (= erroneous = not required to be caught/diagnosed or to do anything even remotely reasonable). However, any function that is or could have been defined in nonprototype aka K&R1 aka oldstyle form must be callable using a (K&R1-style) 'pointer to function of unspecified arguments'. In practice this means that most systems use a compatible calling sequence for at least all nonvarargs functions, so pointers to any of them actually work interchangeably. I have seen platforms, but only a handful, where varargs are different, and mixing pointers to them (or misdeclaring) does cause (serious) problems. > other pointers can have their own representation. All pointers > can be converted to and from pointers to void, without loss. And All _data_ pointers can be converted to and from void* without loss. All function pointers can be converted to other function pointers without loss; at least formally you must convert back before using. > pointers can have different sizes and different patterns for the > null pointer. I suspect a lot of code would fail if compilers > wanted to exercise their full freedoms! Agree with both of those. - David.Thompson1 at worldnet.att.net ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-19 19:20 ` Martin Krischik 2006-03-19 20:43 ` Dr. Adrian Wrigley @ 2006-03-20 9:40 ` Maciej Sobczak 2006-03-20 15:09 ` Robert A Duff 1 sibling, 1 reply; 91+ messages in thread From: Maciej Sobczak @ 2006-03-20 9:40 UTC (permalink / raw) Martin Krischik wrote: > Only a very few C/C++ programmers > actually master the language. As is true for any language that is at least moderately useful. -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/ ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-20 9:40 ` Maciej Sobczak @ 2006-03-20 15:09 ` Robert A Duff 2006-03-21 8:07 ` Maciej Sobczak 0 siblings, 1 reply; 91+ messages in thread From: Robert A Duff @ 2006-03-20 15:09 UTC (permalink / raw) Maciej Sobczak <no.spam@no.spam.com> writes: > Martin Krischik wrote: > > > Only a very few C/C++ programmers > > actually master the language. > > As is true for any language that is at least moderately useful. True. Language designers ought to take that into account -- whenever possible, try to design features subtle misunderstandings are unlikely to cause bugs. Suppose an Ada programmer and a C++ programmer both think that null/NULL must be represented as all-zero-bits. Both programmers are confused. But which programmer is more likely to write code that won't work on a machine where the assumption turns out to be false? - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-20 15:09 ` Robert A Duff @ 2006-03-21 8:07 ` Maciej Sobczak 2006-03-26 18:53 ` Robert A Duff 0 siblings, 1 reply; 91+ messages in thread From: Maciej Sobczak @ 2006-03-21 8:07 UTC (permalink / raw) Robert A Duff wrote: >>>Only a very few C/C++ programmers >>>actually master the language. >> >>As is true for any language that is at least moderately useful. > > True. Language designers ought to take that into account -- whenever > possible, try to design features subtle misunderstandings are unlikely > to cause bugs. True, I don't have any doubts about it. > Suppose an Ada programmer and a C++ programmer both think that null/NULL > must be represented as all-zero-bits. Both programmers are confused. Both programmers take assumptions which are equally wrong. > But which programmer is more likely to write code that won't work > on a machine where the assumption turns out to be false? Naither of those programmer should have any problems with their programs, because pointers are, well, pointers, not integers. Neither of them should have any temptation to interpret pointers as numbers, so that the actual "value" of the pointer never really matters. Even the question "is the NULL pointer zero?" makes no sense in this light, unless you target specific piece of silicon (see my replies to Martin Krischik). In practice, in the world of pointers it's not the NULL pointer representation which is causing problems, but rather unconstrained pointer arithmetics. -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/ ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-21 8:07 ` Maciej Sobczak @ 2006-03-26 18:53 ` Robert A Duff 0 siblings, 0 replies; 91+ messages in thread From: Robert A Duff @ 2006-03-26 18:53 UTC (permalink / raw) Maciej Sobczak <no.spam@no.spam.com> writes: > Robert A Duff wrote: > > >>>Only a very few C/C++ programmers > >>>actually master the language. > >> > >>As is true for any language that is at least moderately useful. > > True. Language designers ought to take that into account -- whenever > > possible, try to design features subtle misunderstandings are unlikely > > to cause bugs. > > True, I don't have any doubts about it. > > > Suppose an Ada programmer and a C++ programmer both think that null/NULL > > must be represented as all-zero-bits. Both programmers are confused. > > Both programmers take assumptions which are equally wrong. Right. > > But which programmer is more likely to write code that won't work > > on a machine where the assumption turns out to be false? > > Naither of those programmer should have any problems with their > programs, because pointers are, well, pointers, not integers. Neither of > them should have any temptation to interpret pointers as numbers, so > that the actual "value" of the pointer never really matters. You say "should". But we're talking about confused/wrong programmers. But the C++ programmer has been taught to use "0" as a value of type char* (which pointer value, of course, is not necessarily represented as all-zero-bits). See other posts in this thread, which recommend that style. It's not far from there, to (wrongly) believing that casting an integer zero to pointer will result in null. >... Even the > question "is the NULL pointer zero?" makes no sense in this light, > unless you target specific piece of silicon (see my replies to Martin > Krischik). I agree that the question "is the NULL pointer zero?" makes no sense, but the question "is the NULL pointer represented as zero (in some or all implementations of a certain language)?" makes sense. It's not usually a hardware ("silicon") issue, though. Ada compilers choose to represent null as zero because compilers for other languages do that, and because operating systems arrange for page zero to trap. Also, I think there are some minor efficiency advantages. > In practice, in the world of pointers it's not the NULL pointer > representation which is causing problems, but rather unconstrained > pointer arithmetics. Certainly pointer arithmetic adds extra trouble. But even without that, dereferencing of null pointers is a plentiful source of bugs. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-19 9:35 ` Martin Krischik 2006-03-19 14:52 ` Peter C. Chapin 2006-03-19 18:15 ` Robert A Duff @ 2006-03-19 19:27 ` Jeffrey R. Carter 2 siblings, 0 replies; 91+ messages in thread From: Jeffrey R. Carter @ 2006-03-19 19:27 UTC (permalink / raw) Martin Krischik wrote: > > Of course programming C or C++ on such an OS could be quite challenging > (Write to (void*)0 and you mess up your Proccess Information Descriptor). Programming C/++ on all OSes is quite challenging, by definition. -- Jeff Carter "What I wouldn't give for a large sock with horse manure in it." Annie Hall 42 ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-18 15:06 ` Justin Gombos 2006-03-19 9:35 ` Martin Krischik @ 2006-03-25 21:40 ` Robert A Duff 2006-03-26 0:10 ` Justin Gombos 2006-03-26 3:15 ` Frank J. Lhota 1 sibling, 2 replies; 91+ messages in thread From: Robert A Duff @ 2006-03-25 21:40 UTC (permalink / raw) Justin Gombos <rpbkbq.xax.gld@uluv.kbq> writes: > On 2006-03-18, Robert A Duff <bobduff@shell01.TheWorld.com> wrote: > > > > In Ada, if an object of an access type has no explicit initial > > value, you can't easily tell whether that means "null is a > > meaningful value for this variable, and that's the default I want" > > versus "this variable will be initialized to a meaningful (non-null) > > value later". > > If you want to distinguish between the two possiblities, you could > explicitly initialize your pointers to null in the first case, and not > in the second. Yes, that's a reasonable style, and I use it myself. But there's no compiler support for that style. As far as the language and compiler are concerned, "X: T" and "X: T := null" mean EXACTLY the same thing. It's hard to tell whether the programmer means the same thing in these cases. >... I rarely use access types, So you rarely create trees, linked list, etc? >... and I probably wouldn't do > that myself simply because I find the distinction unimportant for > access types. Regardless, I'm not going to give up the benefit of > having this distinction on non-access scalars simply because my access > type declarations don't have it. > > > This is exactly analogous to the case with integers -- if they were > > default-initialized to zero, you can't easily tell whether zero is > > intended as a meaningful initial value, versus later initialization > > to a meaningful value. > > Integers, and other non-access scalars are different in this case > because you cannot expect zero to have the same meaning. Zero has a > universal meaning with access types, No, zero has no meaning with access types! >... but it could be in range or out > of range for any other type. The ARM selects access types > specifically to get a default initialization of zero for this reason. There is no "default initialization of zero". There is a default-init to null, which has nothing to do with zero (according to the Ada standard). - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-25 21:40 ` Robert A Duff @ 2006-03-26 0:10 ` Justin Gombos 2006-03-26 1:00 ` Robert A Duff 2006-03-26 3:15 ` Frank J. Lhota 1 sibling, 1 reply; 91+ messages in thread From: Justin Gombos @ 2006-03-26 0:10 UTC (permalink / raw) On 2006-03-25, Robert A Duff <bobduff@shell01.TheWorld.com> wrote: > Justin Gombos <rpbkbq.xax.gld@uluv.kbq> writes: > > So you rarely create trees, linked list, etc? That's right. In fact, a few months ago was the first time I implemented a dynamic container in Ada since I studied it in school. I haven't had a need for them in any of the avionics systems that I've worked. >> Integers, and other non-access scalars are different in this case >> because you cannot expect zero to have the same meaning. Zero has >> a universal meaning with access types, > > No, zero has no meaning with access types! > >>... but it could be in range or out of range for any other type. >>The ARM selects access types specifically to get a default >>initialization of zero for this reason. > > There is no "default initialization of zero". There is a > default-init to null, which has nothing to do with zero (according > to the Ada standard). You're forgetting why we got side tracked on this discussion. Your comment was: I'm not sure what the right answer is, but surely all the arguments for and against dummy values apply equally to access types. Access types are special, and get different treatment than other scalars because they include in their set a representation for a null value. Integers do not; so the same arguements for implicit initialization of access values do not necessarily apply. Whether null values are actually represented as zeros is irrelevant to this matter. Even if null values are nonzero, integers still do not have a null object. -- PM instructions: do a C4esar Ciph3r on my address; retain punctuation. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-26 0:10 ` Justin Gombos @ 2006-03-26 1:00 ` Robert A Duff 2006-03-26 6:37 ` Jeffrey R. Carter 0 siblings, 1 reply; 91+ messages in thread From: Robert A Duff @ 2006-03-26 1:00 UTC (permalink / raw) Justin Gombos <rpbkbq.xax.gld@uluv.kbq> writes: > On 2006-03-25, Robert A Duff <bobduff@shell01.TheWorld.com> wrote: > > Justin Gombos <rpbkbq.xax.gld@uluv.kbq> writes: > > > > So you rarely create trees, linked list, etc? > > That's right. In fact, a few months ago was the first time I > implemented a dynamic container in Ada since I studied it in school. > I haven't had a need for them in any of the avionics systems that I've > worked. OK. I'm a compiler writer, so I use pointers (access types or whatever) quite a lot. > >> Integers, and other non-access scalars are different in this case > >> because you cannot expect zero to have the same meaning. Zero has > >> a universal meaning with access types, > > > > No, zero has no meaning with access types! > > > >>... but it could be in range or out of range for any other type. > >>The ARM selects access types specifically to get a default > >>initialization of zero for this reason. > > > > There is no "default initialization of zero". There is a > > default-init to null, which has nothing to do with zero (according > > to the Ada standard). > > You're forgetting why we got side tracked on this discussion. Sorry. These discussions tend to ramble a bit. ;-) >...Your > comment was: > > I'm not sure what the right answer is, but surely all the arguments > for and against dummy values apply equally to access types. And I stand by that comment. > Access types are special, and get different treatment than other > scalars because they include in their set a representation for a null > value. Yes, access types in Ada are special, because they have a special null value. C and Pascal and so forth are similar. But it doesn't HAVE to be that way. Some languages (SML comes to mind) do not have a special null value provided for free -- if you want one, you declare one. (Or, if you want two, you declare two!) >...Integers do not; so the same arguements for implicit > initialization of access values do not necessarily apply. Again, it doesn't have to be that way. The language designer could provide a special value for integers, too. Most of the time, I do not want a special null value (neither for access types nor for integers). I would prefer a language that did not give me special null values for free -- they're just a tripping hazard, except when I want them. The Ada 2005 "not null" thing is somewhat helpful, in this regard. > Whether null values are actually represented as zeros is irrelevant to > this matter. Quite true. Sorry -- I was confused by your referring to zero as a null access value. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-26 1:00 ` Robert A Duff @ 2006-03-26 6:37 ` Jeffrey R. Carter 2006-03-26 15:43 ` Justin Gombos 2006-03-26 16:51 ` Robert A Duff 0 siblings, 2 replies; 91+ messages in thread From: Jeffrey R. Carter @ 2006-03-26 6:37 UTC (permalink / raw) Robert A Duff wrote: > Justin Gombos <rpbkbq.xax.gld@uluv.kbq> writes: >> Access types are special, and get different treatment than other >> scalars because they include in their set a representation for a null >> value. > > Yes, access types in Ada are special, because they have a special null > value. C and Pascal and so forth are similar. But it doesn't HAVE to > be that way. Some languages (SML comes to mind) do not have a special > null value provided for free -- if you want one, you declare one. > (Or, if you want two, you declare two!) I think we're missing the point. Access types are NOT scalar types in Ada. C pointers may be, since you can treat them pretty much like integers. The ARM TOC has 3.5 Scalar Types 3.5.1 Enumeration Types 3.5.2 Character Types 3.5.3 Boolean Types 3.5.4 Integer Types 3.5.5 Operations of Discrete Types 3.5.6 Real Types 3.5.7 Floating Point Types 3.5.8 Operations of Floating Point Types 3.5.9 Fixed Point Types 3.5.10 Operations of Fixed Point Types and 3.10 Access Types 3.10.1 Incomplete Type Declarations 3.10.2 Operations of Access Types Access types are NOT in the section for scalar types (3.5); they are in their own, separate section (3.10). Once you accept that access types are not scalar types, arguing about the meaning of null changes. Access types are an abstraction, and the concept of null is part of that abstraction. In the abstraction, an access value either designates an object or it doesn't; = null means the former and /= null, the latter. How that is represented is an implementation detail hidden from the user. You could have something sort of equivalent to type Access_Type is private; null : constant Access_Type; private type Access_Type (Designates_Something : Boolean := False) is record case Designates_Something is when False => null; when True => Data : System.Address; -- other fields as needed end case; end record; null : constant Access_Value := (Designates_Something => False); (though I doubt any compiler actually does). Access types aren't special compared to scalar types because they're not scalar types; they're not even conceptually similar. -- Jeff Carter "I spun around, and there I was, face to face with a six-year-old kid. Well, I just threw my guns down and walked away. Little bastard shot me in the ass." Blazing Saddles 40 ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-26 6:37 ` Jeffrey R. Carter @ 2006-03-26 15:43 ` Justin Gombos 2006-03-26 16:32 ` Robert A Duff 2006-03-26 16:51 ` Robert A Duff 1 sibling, 1 reply; 91+ messages in thread From: Justin Gombos @ 2006-03-26 15:43 UTC (permalink / raw) On 2006-03-26, Jeffrey R. Carter <spam.not.jrcarter@acm.not.spam.org> wrote: > > I think we're missing the point. Access types are NOT scalar types > in Ada. C pointers may be, since you can treat them pretty much like > integers. I believe you're right. I had the idea that access types are scalars from page 18 of Michael Feldman's book "Software Construction and Data Structures with Ada 95," but apparently he's wrong about that. > Access types aren't special compared to scalar types because they're > not scalar types; they're not even conceptually similar. Exactly, so it's reasonable to treat access types differently when it comes to default initialization, despite Robert Duffs comment that the arguments for/against apply to both kinds of types. After reading Duff's last post, I can see that he was talking outside of the language, so that's where the misunderstanding was. My position had a premise that we're dealing with Ada integers as they are (that is, non-abstract, and without a null value). -- PM instructions: do a C4esar Ciph3r on my address; retain punctuation. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-26 15:43 ` Justin Gombos @ 2006-03-26 16:32 ` Robert A Duff 0 siblings, 0 replies; 91+ messages in thread From: Robert A Duff @ 2006-03-26 16:32 UTC (permalink / raw) Justin Gombos <rpbkbq.xax.gld@uluv.kbq> writes: >...After reading > Duff's last post, I can see that he was talking outside of the > language, ... Yes, of course! We were talking about how Ada _ought_ to deal with uninitialized variables. Therefore, we must be talking about hypothetical languages that are different from Ada. >...so that's where the misunderstanding was. My position had a > premise that we're dealing with Ada integers as they are (that is, > non-abstract, and without a null value). Yes, access types have null, and integers do not (in Ada). But that's not a good argument that access types _should_ have null, or that integers should _not_ have null. "It's best if Ada does X, because Ada does X" -- that's circular reasoning. ;-) - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-26 6:37 ` Jeffrey R. Carter 2006-03-26 15:43 ` Justin Gombos @ 2006-03-26 16:51 ` Robert A Duff 2006-03-26 19:41 ` Jeffrey R. Carter 1 sibling, 1 reply; 91+ messages in thread From: Robert A Duff @ 2006-03-26 16:51 UTC (permalink / raw) "Jeffrey R. Carter" <spam.not.jrcarter@acm.not.spam.org> writes: > Access types are NOT in the section for scalar types (3.5); they are in > their own, separate section (3.10). Once you accept that access types > are not scalar types,... Sorry, but I don't "get" this argument. I accept that access types are not scalar types. Both are "elementary" types, however. I don't see any fundamental difference between access and scalar that would imply that uninit vars should be treated differently for the two. Of course, there are many fundamental differences, which imply a different set of operations (can't do arithmetic on access values, can't do 'Access and get an integer, etc). But there are also many things in commmon between scalar and access: both can be passed as parameters, both can be stored as record components, both are by-copy types. An uninit var should be considered a bug, whether it's access or integer. I see no fundamental difference, here. Defaulting to null hides this bug. >... arguing about the meaning of null changes. Access > types are an abstraction, and the concept of null is part of that > abstraction. In the abstraction, an access value either designates an > object or it doesn't; = null means the former and /= null, the > latter. Yes, but my claim is that that's a poorly designed abstraction. In most cases, null is just a tripping hazard. The programmer should have the choice -- access type without any special value, access type with a special value that doesn't designate anything, access type with _two_ special values, ... Ada 2005 comes closer, by having "not null" -- but the default is backwards (for obvious compatibility reasons). Note that when I declare a private type, I choose whether it should have "special" values, and what they mean. And I choose whether a special value is used as a default. I can choose to raise an exception if clients look at an uninit var. I can choose to prevent uninit vars statically, using (<>) discriminants. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-26 16:51 ` Robert A Duff @ 2006-03-26 19:41 ` Jeffrey R. Carter 0 siblings, 0 replies; 91+ messages in thread From: Jeffrey R. Carter @ 2006-03-26 19:41 UTC (permalink / raw) Robert A Duff wrote: > > An uninit var should be considered a bug, whether it's access or > integer. I see no fundamental difference, here. Defaulting to null > hides this bug. This only holds true for types that don't have meaningful default initial values. I've written lots of types for which an uninitialized variable of the type is perfectly reasonable, and even the expected behavior. Usually they're defined as "[limited] private". I don't expect users of a data structure to have to make a special initialization call to be able to use the structure. Whether the default initial value for access types is a good choice is not something I'm debating. I'm simply saying that default initial values are not a bad thing for ADTs, an access type is closer to an ADT than to a scalar type, and using the same criteria for both doesn't compute. > Yes, but my claim is that that's a poorly designed abstraction. > In most cases, null is just a tripping hazard. > The programmer should have the choice -- access type without > any special value, access type with a special value that doesn't > designate anything, access type with _two_ special values, ... That may be, but because it's an abstraction, it's not similar to scalar types, and so arguments that apply to scalar types don't necessarily apply. > Note that when I declare a private type, I choose whether it should have > "special" values, and what they mean. And I choose whether a special > value is used as a default. I can choose to raise an exception if > clients look at an uninit var. I can choose to prevent uninit > vars statically, using (<>) discriminants. Access types are like a private type. The only difference is that access types are part of the core language, and don't carry all the extra syntax that defining them as an explicit private type would add. Ichbiah and company chose that the abstraction called access types should have a "special" value, and what it means. They chose that a special value is used as a default. They chose to raise an exception if clients apply certain operations to an uninitialized variable. They may not be the choices you would make for this abstraction, but your choices may not be what others would choose, also. -- Jeff Carter "My name is Jim, but most people call me ... Jim." Blazing Saddles 39 ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-25 21:40 ` Robert A Duff 2006-03-26 0:10 ` Justin Gombos @ 2006-03-26 3:15 ` Frank J. Lhota 2006-03-26 18:28 ` Robert A Duff 1 sibling, 1 reply; 91+ messages in thread From: Frank J. Lhota @ 2006-03-26 3:15 UTC (permalink / raw) "Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message news:wccr74q19up.fsf@shell01.TheWorld.com... >>... I rarely use access types, > > So you rarely create trees, linked list, etc? Not necessarily; One could create these entities using a container library such as the Booch components or the 2005 Ada Containers. Of course, such libraries will use acess types in their implementation, but the end user does not have to handle access values directly. -- "All things extant in this world, Gods of Heaven, gods of Earth, Let everything be as it should be; Thus shall it be!" - Magical chant from "Magical Shopping Arcade Abenobashi" "Drizzle, Drazzle, Drozzle, Drome, Time for this one to come home!" - Mr. Lizard from "Tooter Turtle" ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-26 3:15 ` Frank J. Lhota @ 2006-03-26 18:28 ` Robert A Duff 2006-03-26 19:43 ` Jeffrey R. Carter 2006-03-26 19:59 ` Simon Wright 0 siblings, 2 replies; 91+ messages in thread From: Robert A Duff @ 2006-03-26 18:28 UTC (permalink / raw) "Frank J. Lhota" <NOSPAM.FrankLho@rcn.com> writes: > "Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message > news:wccr74q19up.fsf@shell01.TheWorld.com... > >>... I rarely use access types, > > > > So you rarely create trees, linked list, etc? > > Not necessarily; One could create these entities using a container library > such as the Booch components or the 2005 Ada Containers. Of course, such > libraries will use acess types in their implementation, but the end user > does not have to handle access values directly. Good point. At least for the "linked lists, etc" part. But for trees and symbol tables and the like, as in a compiler, those container libraries are no help. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-26 18:28 ` Robert A Duff @ 2006-03-26 19:43 ` Jeffrey R. Carter 2006-03-26 19:59 ` Simon Wright 1 sibling, 0 replies; 91+ messages in thread From: Jeffrey R. Carter @ 2006-03-26 19:43 UTC (permalink / raw) Robert A Duff wrote: > > But for trees and symbol tables and the like, as in a compiler, > those container libraries are no help. I would think by now you would have created domain-specific packages to encapsulate these concepts for your language-processing tool development work, and still not have to deal directly with the access types. -- Jeff Carter "My name is Jim, but most people call me ... Jim." Blazing Saddles 39 ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: private types 2006-03-26 18:28 ` Robert A Duff 2006-03-26 19:43 ` Jeffrey R. Carter @ 2006-03-26 19:59 ` Simon Wright 1 sibling, 0 replies; 91+ messages in thread From: Simon Wright @ 2006-03-26 19:59 UTC (permalink / raw) Robert A Duff <bobduff@shell01.TheWorld.com> writes: > But for trees and symbol tables and the like, as in a compiler, > those container libraries are no help. What is so special about trees and symbol tables? (I can see that application-specific optimisation might be a problem). ^ permalink raw reply [flat|nested] 91+ messages in thread
end of thread, other threads:[~2006-03-27 4:07 UTC | newest] Thread overview: 91+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2006-03-13 19:58 private types ada_student 2006-03-13 20:27 ` Mark Lorenzen 2006-03-13 21:05 ` Pascal Obry 2006-03-13 21:07 ` ada_student 2006-03-13 21:45 ` Simon Wright 2006-03-14 4:51 ` Jeffrey R. Carter 2006-03-14 7:44 ` Brian May 2006-03-14 8:25 ` Ludovic Brenta 2006-03-14 8:47 ` Alex R. Mosteo 2006-03-17 4:33 ` Justin Gombos 2006-03-17 5:17 ` Brian May 2006-03-17 22:50 ` Justin Gombos 2006-03-18 1:17 ` Randy Brukardt 2006-03-18 2:17 ` Justin Gombos 2006-03-21 0:08 ` Randy Brukardt 2006-03-18 8:39 ` Uninitialized variables (was: Re: private types) Dirk Craeynest 2006-03-18 14:06 ` Gautier 2006-03-18 14:36 ` Uninitialized variables Jeffrey Creem 2006-03-21 0:22 ` Uninitialized variables (was: Re: private types) Randy Brukardt 2006-03-21 0:38 ` Randy Brukardt 2006-03-18 12:06 ` private types Martin Dowie 2006-03-18 12:47 ` Robert A Duff 2006-03-17 7:40 ` Maciej Sobczak 2006-03-17 16:41 ` Frank J. Lhota 2006-03-17 23:36 ` Justin Gombos 2006-03-18 1:32 ` Randy Brukardt 2006-03-18 3:21 ` Handling invalid objects Justin Gombos 2006-03-18 7:35 ` Jeffrey R. Carter 2006-03-18 16:10 ` Justin Gombos 2006-03-19 11:00 ` Simon Wright 2006-03-20 23:57 ` Randy Brukardt 2006-03-22 2:06 ` Justin Gombos 2006-03-22 5:23 ` tmoran 2006-03-22 8:48 ` Dmitry A. Kazakov 2006-03-22 9:24 ` Maciej Sobczak 2006-03-22 11:05 ` Dmitry A. Kazakov 2006-03-22 16:42 ` Maciej Sobczak 2006-03-22 18:06 ` Stefan Lucks 2006-03-23 13:20 ` Dmitry A. Kazakov 2006-03-18 8:57 ` Jacob Sparre Andersen 2006-03-19 19:07 ` Dr. Adrian Wrigley 2006-03-20 15:25 ` Robert A Duff 2006-03-19 22:06 ` Brian May 2006-03-20 21:17 ` Jeffrey R. Carter 2006-03-20 23:44 ` Randy Brukardt 2006-03-22 1:27 ` Justin Gombos 2006-03-18 9:20 ` private types Dmitry A. Kazakov 2006-03-17 13:18 ` Robert A Duff 2006-03-17 23:44 ` Justin Gombos 2006-03-18 9:24 ` Dmitry A. Kazakov 2006-03-18 12:56 ` Robert A Duff 2006-03-18 15:06 ` Justin Gombos 2006-03-19 9:35 ` Martin Krischik 2006-03-19 14:52 ` Peter C. Chapin 2006-03-19 15:08 ` Björn Persson 2006-03-19 16:34 ` Martin Krischik 2006-03-20 9:57 ` Maciej Sobczak 2006-03-20 10:58 ` Peter C. Chapin 2006-03-20 11:19 ` Peter C. Chapin 2006-03-20 13:06 ` Maciej Sobczak 2006-03-20 15:19 ` Robert A Duff 2006-03-20 16:47 ` James Dennett 2006-03-20 19:12 ` Martin Krischik 2006-03-21 7:27 ` Maciej Sobczak 2006-03-20 19:32 ` Martin Krischik 2006-03-21 7:41 ` Maciej Sobczak 2006-03-20 20:29 ` Simon Wright 2006-03-19 17:43 ` Larry Kilgallen 2006-03-19 22:11 ` Peter C. Chapin 2006-03-19 18:15 ` Robert A Duff 2006-03-19 19:20 ` Martin Krischik 2006-03-19 20:43 ` Dr. Adrian Wrigley 2006-03-20 15:01 ` Robert A Duff 2006-03-27 4:07 ` Dave Thompson 2006-03-20 9:40 ` Maciej Sobczak 2006-03-20 15:09 ` Robert A Duff 2006-03-21 8:07 ` Maciej Sobczak 2006-03-26 18:53 ` Robert A Duff 2006-03-19 19:27 ` Jeffrey R. Carter 2006-03-25 21:40 ` Robert A Duff 2006-03-26 0:10 ` Justin Gombos 2006-03-26 1:00 ` Robert A Duff 2006-03-26 6:37 ` Jeffrey R. Carter 2006-03-26 15:43 ` Justin Gombos 2006-03-26 16:32 ` Robert A Duff 2006-03-26 16:51 ` Robert A Duff 2006-03-26 19:41 ` Jeffrey R. Carter 2006-03-26 3:15 ` Frank J. Lhota 2006-03-26 18:28 ` Robert A Duff 2006-03-26 19:43 ` Jeffrey R. Carter 2006-03-26 19:59 ` Simon Wright
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox