* Uninitialized Variables @ 1999-01-25 0:00 Roger Racine 1999-01-25 0:00 ` Tucker Taft 1999-01-25 0:00 ` robert_dewar 0 siblings, 2 replies; 4+ messages in thread From: Roger Racine @ 1999-01-25 0:00 UTC (permalink / raw) One of the few areas where Ada programs exhibit non-deterministic behavior (i.e. different behavior for different runs) is when variables are not set before their use. I am curious as to why the language designers did not think this was sufficiently common enough of an error to protect against it. I understand that having an initial value takes more memory and more CPU, but so do constraint checks. And there could always have been a pragma to allow uninitialized variables (akin to pragma SUPPRESS). By the way, I would be happy with a mechanism at link time that only complained about (or implicitly created initial values for) data that was determined might be used before being set. The problem is that different environments exhibit different behavior. Some environments put zeros in all of RAM as part of initialization. This sometimes masks the problem (which is fine if portability is not a concern). Some put zeros in all static (non-stack, non-heap) variables. Some even allow the user to specify the value to be put in RAM. And some do nothing at all. Does anyone know why there is not at least a required link-time warning message for variables possibly used before being set? Roger Racine ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Uninitialized Variables 1999-01-25 0:00 Uninitialized Variables Roger Racine @ 1999-01-25 0:00 ` Tucker Taft 1999-01-25 0:00 ` robert_dewar 1 sibling, 0 replies; 4+ messages in thread From: Tucker Taft @ 1999-01-25 0:00 UTC (permalink / raw) Roger Racine (rracine@draper.com) wrote: : One of the few areas where Ada programs exhibit non-deterministic behavior : (i.e. different behavior for different runs) is when variables are not set : before their use. : I am curious as to why the language designers did not think this was : sufficiently common enough of an error to protect against it. I don't know the Ada 83 history on this. However, simply default initializing all scalars to something like zero has its own problems, because it can make it less clear whether the default value is the desired initial value, or the programmer forgot to properly set the value. Initializing pointers by default to null has somewhat the same problem, but less so, since any dereference of a null pointer would be caught, whereas any use of a default scalar value would probably not be caught. In any case, Ada 95 does include a pragma "Normalize_Scalars" which forces the implementation to initialize all scalars to some unspecified value, ideally to a value outside of their declared range. The goal here is to create reproducibility, without allowing the programmer to "shirk" their responsibility of initializing the variable properly. : ... I understand : that having an initial value takes more memory and more CPU, but so do : constraint checks. And there could always have been a pragma to allow : uninitialized variables (akin to pragma SUPPRESS). I guess I agree that it is a relatively small price to pay, but it did not seem like something we could insert during the Ada 9X revision. We wanted performance to be compatible with Ada 83 as well! Certainly Bob Duff, a member of the Ada 9X design team, would agree with your suggestions. Note that in Ada 95 we did change the use of an uninitialized variable into a "bounded error" rather than "erroneous." Even this change drew some protests from implementors because of the potential performance effects. : By the way, I would be happy with a mechanism at link time that only : complained about (or implicitly created initial values for) data that was : determined might be used before being set. We have recently added to our Ada 95 front end detection of potentially uninitialized local variables. Detecting potentially uninitialized global variables would require some kind of link-time detection. : The problem is that different environments exhibit different behavior. Some : environments put zeros in all of RAM as part of initialization. This : sometimes masks the problem (which is fine if portability is not a concern). : Some put zeros in all static (non-stack, non-heap) variables. Some even allow : the user to specify the value to be put in RAM. And some do nothing at all. : Does anyone know why there is not at least a required link-time warning : message for variables possibly used before being set? Requiring specific warnings is generally treading on thin ice from a language specification point of view. Even specifying the form of error messages is difficult. This is really more of a quality-of-implementation issue, and not very easy to legislate via the language standard. : Roger Racine -- -Tucker Taft stt@averstar.com http://www.averstar.com/~stt/ Technical Director, Distributed IT Solutions (www.averstar.com/tools) AverStar (formerly Intermetrics, Inc.) Burlington, MA USA ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Uninitialized Variables 1999-01-25 0:00 Uninitialized Variables Roger Racine 1999-01-25 0:00 ` Tucker Taft @ 1999-01-25 0:00 ` robert_dewar 1 sibling, 0 replies; 4+ messages in thread From: robert_dewar @ 1999-01-25 0:00 UTC (permalink / raw) In article <rracine.7.000B4B63@draper.com>, rracine@draper.com (Roger Racine) wrote: > One of the few areas where Ada programs exhibit non-deterministic behavior > (i.e. different behavior for different runs) is when variables are not set > before their use. > > I am curious as to why the language designers did not > think this was sufficiently common enough of an error to > protect against it. I understand that having an initial > value takes more memory and more CPU, but so do > constraint checks. You miss the philosophical and design objections to junk initial values. These arguments are familiar so I won't repeat them in detail here! > And there could always have been a pragma to allow > uninitialized variables (akin to pragma SUPPRESS). Ada 95 of course has a pragma, but it has the opposite sense, you use pragma Normalize_Scalars if you want initializations. The intention of this pragma is precisely to avoid non-determinism. Why is it not enough for you? > Does anyone know why there is not at least a required > link-time warning message for variables possibly used > before being set? First, a full analysis at link time of all possible static flows through a program would be a very heavy burden to place on a compiler. It is far out of reach of what could be done in existing implementation frameworks, and I would have significant efficiency concerns. Second, requiring warning messages is a big bogus in anyway. Such requirements are not testable, and not well-defined. I think it reasonable to let the marketplace determine the need for warnings. It is certainly useful for a compiler to do a reasonable job of detecting obvious cases (try using -gnatwu with GNAT 3.11p). Robert Dewar -----------== Posted via Deja News, The Discussion Network ==---------- http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own ^ permalink raw reply [flat|nested] 4+ messages in thread
* private types @ 2006-03-13 19:58 ada_student 2006-03-17 4:33 ` Justin Gombos 0 siblings, 1 reply; 4+ 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] 4+ messages in thread
* Re: private types @ 2006-03-17 4:33 ` Justin Gombos 2006-03-17 5:17 ` Brian May 0 siblings, 1 reply; 4+ 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] 4+ messages in thread
* Re: private types 2006-03-17 4:33 ` Justin Gombos @ 2006-03-17 5:17 ` Brian May 2006-03-18 1:17 ` Randy Brukardt 0 siblings, 1 reply; 4+ 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] 4+ messages in thread
* Re: private types 2006-03-17 5:17 ` Brian May @ 2006-03-18 1:17 ` Randy Brukardt 2006-03-18 8:39 ` Uninitialized variables (was: Re: private types) Dirk Craeynest 0 siblings, 1 reply; 4+ 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] 4+ messages in thread
* Uninitialized variables (was: Re: private types) 2006-03-18 1:17 ` Randy Brukardt @ 2006-03-18 8:39 ` Dirk Craeynest 2006-03-18 14:06 ` Gautier 0 siblings, 1 reply; 4+ 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] 4+ 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 0 siblings, 1 reply; 4+ 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] 4+ messages in thread
* Re: Uninitialized variables 2006-03-18 14:06 ` Gautier @ 2006-03-18 14:36 ` Jeffrey Creem 0 siblings, 0 replies; 4+ 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] 4+ messages in thread
end of thread, other threads:[~2006-03-18 14:36 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 1999-01-25 0:00 Uninitialized Variables Roger Racine 1999-01-25 0:00 ` Tucker Taft 1999-01-25 0:00 ` robert_dewar -- strict thread matches above, loose matches on Subject: below -- 2006-03-13 19:58 private types ada_student 2006-03-17 4:33 ` Justin Gombos 2006-03-17 5:17 ` Brian May 2006-03-18 1:17 ` 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
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox