* Uninitialized out parameters. @ 2016-04-05 12:02 ahlan 2016-04-05 13:17 ` rieachus ` (2 more replies) 0 siblings, 3 replies; 91+ messages in thread From: ahlan @ 2016-04-05 12:02 UTC (permalink / raw) Hi, Is this a GNAT (GPL-2015) bug or my not understanding Ada? I was surprised that I could compile procedure Test (V : out Positive) is null; and even more by the results of calling the procedure V : Positive; begin Test (V); Ada.Text_IO.Put_Line ("V:" & V'img); The value zero is output, which because V is positive should be impossible. I would have thought that null procedures with out parameters would fail to compile. Opinions anyone? MfG Ahlan ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-05 12:02 Uninitialized out parameters ahlan @ 2016-04-05 13:17 ` rieachus 2016-04-05 14:07 ` ahlan 2016-04-05 16:19 ` G.B. 2016-04-06 11:37 ` AdaMagica 2 siblings, 1 reply; 91+ messages in thread From: rieachus @ 2016-04-05 13:17 UTC (permalink / raw) On Tuesday, April 5, 2016 at 8:02:51 AM UTC-4, ah...@marriott.org wrote: > Hi, > > Is this a GNAT (GPL-2015) bug or my not understanding Ada? > > I was surprised that I could compile > procedure Test (V : out Positive) is null; > > and even more by the results of calling the procedure > > V : Positive; > begin > Test (V); > Ada.Text_IO.Put_Line ("V:" & V'img); > > The value zero is output, which because V is positive should be impossible. > > I would have thought that null procedures with out parameters would fail to compile. > > Opinions anyone? > > MfG > Ahlan There are two issues here. One is whether this program is 'legal' Ada. Short answer, there are many, many more Ada programs than Ada programs that "make sense." This is just another example. The second issue? Are compilers allowed to warn you about this code? Sure. But why allow it? Right now I am working on a generic package where GNAT warns me that some of the code in an instantiation will Constraint_Error if executed. But it can only be reached if the generic is instantiated with a generic formal such that the code will not raise an error. I'll add pragma Suppress (Index_Check) before I'm done, but for now, if a fifth warning shows up, I'll know to be concerned. ;-) Is it possible to write code which will only raise an error if Fermat's Last Theorem is false? Sure, I've done it. I did it just to show that a proposal for elaboration order checking was flawed. The ARG navigates a fine line between allowing all useful programs to be written, and requiring compilers to do tons of checks for unintended errors. Look for example at 6.5.1 Nonreturning procedures. Is it meaningful for a nonreturning procedure to set an out parameter? Should a compiler be required to make that check? (Either for or against.) The answer is that Ada is used in many contexts where nonreturning procedures are meaningful--I normally did so in flight guidance software. For manned aircraft you certainly want to be sure that the main processing loop never exits while power is on. But the intersection of a parameter check and nonreturning procedures (whatever you would expect that check to do) is just making unnecessary work for the compiler. Similarly a procedure may be called with an out parameter that already has a value. So it is the programmer's job to deal with the union of these issues in a sensible way. Could GNAT (or any other) compiler provide a warning? Sure, and it does: procedure NoSet is Counter: Positive; procedure Reset (V : out Positive; User_Check: Boolean := True) is function Ask_User return Boolean is begin return True; end; -- TBD begin if User_Check and then Ask_User then return; end if; V := 1; end Reset; begin Reset(Counter); end NoSet; gnatmake -O3 noset.adb gcc -c -O3 noset.adb noset.adb:7:42: warning: "out" parameter "V" not set before return gnatbind -x noset.ali gnatlink noset.ali -O3 Compilation finished at Tue Apr 05 09:13:54 ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-05 13:17 ` rieachus @ 2016-04-05 14:07 ` ahlan 2016-04-06 9:45 ` Mark Lorenzen 0 siblings, 1 reply; 91+ messages in thread From: ahlan @ 2016-04-05 14:07 UTC (permalink / raw) On Tuesday, April 5, 2016 at 3:17:46 PM UTC+2, riea...@comcast.net wrote: > On Tuesday, April 5, 2016 at 8:02:51 AM UTC-4, ah...@marriott.org wrote: > > Hi, > > > > Is this a GNAT (GPL-2015) bug or my not understanding Ada? > > > > I was surprised that I could compile > > procedure Test (V : out Positive) is null; > > > > and even more by the results of calling the procedure > > > > V : Positive; > > begin > > Test (V); > > Ada.Text_IO.Put_Line ("V:" & V'img); > > > > The value zero is output, which because V is positive should be impossible. > > > > I would have thought that null procedures with out parameters would fail to compile. > > > > Opinions anyone? > > > > MfG > > Ahlan > > There are two issues here. One is whether this program is 'legal' Ada. Short answer, there are many, many more Ada programs than Ada programs that "make sense." This is just another example. The second issue? Are compilers allowed to warn you about this code? Sure. But why allow it? Right now I am working on a generic package where GNAT warns me that some of the code in an instantiation will Constraint_Error if executed. But it can only be reached if the generic is instantiated with a generic formal such that the code will not raise an error. I'll add pragma Suppress (Index_Check) before I'm done, but for now, if a fifth warning shows up, I'll know to be concerned. ;-) > > Is it possible to write code which will only raise an error if Fermat's Last Theorem is false? Sure, I've done it. I did it just to show that a proposal for elaboration order checking was flawed. The ARG navigates a fine line between allowing all useful programs to be written, and requiring compilers to do tons of checks for unintended errors. Look for example at 6.5.1 Nonreturning procedures. > > Is it meaningful for a nonreturning procedure to set an out parameter? Should a compiler be required to make that check? (Either for or against.) The answer is that Ada is used in many contexts where nonreturning procedures are meaningful--I normally did so in flight guidance software. For manned aircraft you certainly want to be sure that the main processing loop never exits while power is on. But the intersection of a parameter check and nonreturning procedures (whatever you would expect that check to do) is just making unnecessary work for the compiler. Similarly a procedure may be called with an out parameter that already has a value. So it is the programmer's job to deal with the union of these issues in a sensible way. > > Could GNAT (or any other) compiler provide a warning? Sure, and it does: > > procedure NoSet is > Counter: Positive; > procedure Reset (V : out Positive; > User_Check: Boolean := True) is > function Ask_User return Boolean is begin return True; end; -- TBD > begin > if User_Check and then Ask_User then return; end if; > V := 1; > end Reset; > begin > Reset(Counter); > end NoSet; > > gnatmake -O3 noset.adb > gcc -c -O3 noset.adb > noset.adb:7:42: warning: "out" parameter "V" not set before return > gnatbind -x noset.ali > gnatlink noset.ali -O3 > > Compilation finished at Tue Apr 05 09:13:54 Hi, You write "Could GNAT (or any other) compiler provide a warning? Sure, and it does: " but that's my whole point - GNAT doesn't in my example. And I feel that it should. A null procedure is NOT a non-returning procedure - it does return and moreover in my example actually returns an illegal value! In my gpr I compile with package Compiler is for Default_Switches ("ada") use ("-O1", "-gnatQ", "-gnato", "-g", "-gnat12", "-gnatwcehijkmopruvz.c.n.p.t.w.x", "-gnatykmpM120"); end Compiler; Is there a warning that I need to explicitly switch on in order that GNAT checks for out parameters in null procedures? MfG Ahlan ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-05 14:07 ` ahlan @ 2016-04-06 9:45 ` Mark Lorenzen 2016-04-06 21:01 ` Jeffrey R. Carter 2016-04-07 7:10 ` ahlan 0 siblings, 2 replies; 91+ messages in thread From: Mark Lorenzen @ 2016-04-06 9:45 UTC (permalink / raw) On Tuesday, April 5, 2016 at 4:07:18 PM UTC+2, ah...@marriott.org wrote: > > In my gpr I compile with > package Compiler is > for Default_Switches ("ada") use ("-O1", "-gnatQ", "-gnato", "-g", "-gnat12", > "-gnatwcehijkmopruvz.c.n.p.t.w.x", "-gnatykmpM120"); > end Compiler; > > Is there a warning that I need to explicitly switch on in order that GNAT checks for out parameters in null procedures? You have enabled a lot of warnings, but why not start with -gnatwa? That is usually a good starting point and then you can add further swicthes. Try to add -gnatwf that should enable warnings about unreferenced formal parameters. You can also use the GNATcheck tool to check your coding standard. GNATcheck is able to find some instances of unassigned out parameters (rule Unassigned_OUT_Parameters). If you want to be 100% sure that you do not have uninitialized variable or out parameters, you will need to use a stronger static analysis tool. Regards, Mark L ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 9:45 ` Mark Lorenzen @ 2016-04-06 21:01 ` Jeffrey R. Carter 2016-04-07 7:10 ` ahlan 1 sibling, 0 replies; 91+ messages in thread From: Jeffrey R. Carter @ 2016-04-06 21:01 UTC (permalink / raw) On Tuesday, April 5, 2016 at 4:07:18 PM UTC+2, ah...@marriott.org wrote: > > In my gpr I compile with > package Compiler is > for Default_Switches ("ada") use ("-O1", "-gnatQ", "-gnato", "-g", "-gnat12", > "-gnatwcehijkmopruvz.c.n.p.t.w.x", "-gnatykmpM120"); > end Compiler; I think the first question is whether the procedure is called at all. Since the compiler knows it's null and so is supposed to do nothing, and since optimization is turned on, it seems a reasonable optimization to eliminate the call. The the value passed to 'Img is whatever bits you get from an uninitialized variable of the type. -- Jeff Carter "You can never forget too much about C++." 115 ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 9:45 ` Mark Lorenzen 2016-04-06 21:01 ` Jeffrey R. Carter @ 2016-04-07 7:10 ` ahlan 1 sibling, 0 replies; 91+ messages in thread From: ahlan @ 2016-04-07 7:10 UTC (permalink / raw) On Wednesday, April 6, 2016 at 11:45:02 AM UTC+2, Mark Lorenzen wrote: > On Tuesday, April 5, 2016 at 4:07:18 PM UTC+2, ah...@marriott.org wrote: > > > > In my gpr I compile with > > package Compiler is > > for Default_Switches ("ada") use ("-O1", "-gnatQ", "-gnato", "-g", "-gnat12", > > "-gnatwcehijkmopruvz.c.n.p.t.w.x", "-gnatykmpM120"); > > end Compiler; > > > > Is there a warning that I need to explicitly switch on in order that GNAT checks for out parameters in null procedures? > > You have enabled a lot of warnings, but why not start with -gnatwa? That is usually a good starting point and then you can add further swicthes. Try to add -gnatwf that should enable warnings about unreferenced formal parameters. > > You can also use the GNATcheck tool to check your coding standard. GNATcheck is able to find some instances of unassigned out parameters (rule Unassigned_OUT_Parameters). If you want to be 100% sure that you do not have uninitialized variable or out parameters, you will need to use a stronger static analysis tool. > > Regards, > Mark L We use -gnatwu which includes -gnatwf ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-05 12:02 Uninitialized out parameters ahlan 2016-04-05 13:17 ` rieachus @ 2016-04-05 16:19 ` G.B. 2016-04-06 8:19 ` ahlan 2016-04-06 11:37 ` AdaMagica 2 siblings, 1 reply; 91+ messages in thread From: G.B. @ 2016-04-05 16:19 UTC (permalink / raw) On 05.04.16 14:02, ahlan@marriott.org wrote: > Ada.Text_IO.Put_Line ("V:" & V'img); > > The value zero is output, which because V is positive should be impossible. Addressing just this issue: the line is calling implementation defined attribute 'IMG, which can do as it pleases. The Ada type attribute 'Image takes a value of type Positive'Base, which includes 0, which is why outputting 0 is perfectly fine. (It's not a subtype attribute, but a type attribute, if this makes sense.) ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-05 16:19 ` G.B. @ 2016-04-06 8:19 ` ahlan 2016-04-06 10:17 ` G.B. 0 siblings, 1 reply; 91+ messages in thread From: ahlan @ 2016-04-06 8:19 UTC (permalink / raw) On Tuesday, April 5, 2016 at 6:19:47 PM UTC+2, G.B. wrote: > On 05.04.16 14:02, ahlan@marriott.org wrote: > > Ada.Text_IO.Put_Line ("V:" & V'img); > > > > The value zero is output, which because V is positive should be impossible. > > Addressing just this issue: the line is calling > implementation defined attribute 'IMG, which can > do as it pleases. The Ada type attribute 'Image > takes a value of type Positive'Base, which includes 0, > which is why outputting 0 is perfectly fine. > > (It's not a subtype attribute, but a type attribute, > if this makes sense.) The issue here is not whether or not 'img fails but the fact that V is returned with a value out of range. But even that is not the point I'm trying to make. I am suggesting that it ought not to be possible to define a null procedure that has out parameters without some form of warning being issued. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 8:19 ` ahlan @ 2016-04-06 10:17 ` G.B. 2016-04-06 11:44 ` Dennis Lee Bieber 2016-04-06 20:47 ` Randy Brukardt 0 siblings, 2 replies; 91+ messages in thread From: G.B. @ 2016-04-06 10:17 UTC (permalink / raw) On 06.04.16 10:19, ahlan@marriott.org wrote: > On Tuesday, April 5, 2016 at 6:19:47 PM UTC+2, G.B. wrote: >> On 05.04.16 14:02, ahlan@marriott.org wrote: >>> Ada.Text_IO.Put_Line ("V:" & V'img); >>> >>> The value zero is output, which because V is positive should be impossible. >> >> Addressing just this issue: the line is calling >> implementation defined attribute 'IMG, which can >> do as it pleases. The Ada type attribute 'Image >> takes a value of type Positive'Base, which includes 0, >> which is why outputting 0 is perfectly fine. >> >> (It's not a subtype attribute, but a type attribute, >> if this makes sense.) > > The issue here is not whether or not 'img fails but the fact that V is returned with a value out of range. The issue is rather, I think, whether V is returned at all. There would have to be an assignment within the null procedure. > But even that is not the point I'm trying to make. > I am suggesting that it ought not to be possible to define a null procedure that has out parameters without some form of warning being issued. I think the usual answer is that the compiler is not a mind reader and the best you could get is a warning. Who knows? Maybe the technical requirements are such that the programmer uses a procedure like Test as a placeholder, maybe its existence is dictated by an abstract type, maybe a null procedure really should do nothing at all, which includes not touching V. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 10:17 ` G.B. @ 2016-04-06 11:44 ` Dennis Lee Bieber 2016-04-06 20:41 ` Niklas Holsti 2016-04-06 20:54 ` Randy Brukardt 2016-04-06 20:47 ` Randy Brukardt 1 sibling, 2 replies; 91+ messages in thread From: Dennis Lee Bieber @ 2016-04-06 11:44 UTC (permalink / raw) On Wed, 6 Apr 2016 12:17:05 +0200, "G.B." <bauhaus@futureapps.invalid> declaimed the following: >On 06.04.16 10:19, ahlan@marriott.org wrote: >> On Tuesday, April 5, 2016 at 6:19:47 PM UTC+2, G.B. wrote: >>> On 05.04.16 14:02, ahlan@marriott.org wrote: >>>> Ada.Text_IO.Put_Line ("V:" & V'img); >>>> >>>> The value zero is output, which because V is positive should be impossible. >>> >>> Addressing just this issue: the line is calling >>> implementation defined attribute 'IMG, which can >>> do as it pleases. The Ada type attribute 'Image >>> takes a value of type Positive'Base, which includes 0, >>> which is why outputting 0 is perfectly fine. >>> >>> (It's not a subtype attribute, but a type attribute, >>> if this makes sense.) >> >> The issue here is not whether or not 'img fails but the fact that V is returned with a value out of range. > >The issue is rather, I think, whether V is returned at all. >There would have to be an assignment within the null procedure. > Which could be a case if the compiler used copy-in/copy-out semantics for scalars (or just copy-out for the test sample). GNAT, if I recall, uses reference semantics, and as out-only wouldn't be checking the initial value on entry. I'd concur that V is not being returned -- it retains whatever value the uninitialized memory space held on entry. If one must guard, then http://www.adaic.org/resources/add_content/standards/05aarm/html/AA-13-9-2.html may be applicable """ 4 20 Invalid data can be created in the following cases (not counting erroneous or unpredictable execution): 5 an uninitialized scalar object, """ -- Wulfraed Dennis Lee Bieber AF6VN wlfraed@ix.netcom.com HTTP://wlfraed.home.netcom.com/ ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 11:44 ` Dennis Lee Bieber @ 2016-04-06 20:41 ` Niklas Holsti 2016-04-06 20:54 ` Randy Brukardt 1 sibling, 0 replies; 91+ messages in thread From: Niklas Holsti @ 2016-04-06 20:41 UTC (permalink / raw) On 16-04-06 14:44 , Dennis Lee Bieber wrote: > On Wed, 6 Apr 2016 12:17:05 +0200, "G.B." <bauhaus@futureapps.invalid> > declaimed the following: > >> On 06.04.16 10:19, ahlan@marriott.org wrote: >>> On Tuesday, April 5, 2016 at 6:19:47 PM UTC+2, G.B. wrote: >>>> On 05.04.16 14:02, ahlan@marriott.org wrote: >>>>> Ada.Text_IO.Put_Line ("V:" & V'img); >>>>> >>>>> The value zero is output, which because V is positive should be impossible. >>>> >>>> Addressing just this issue: the line is calling >>>> implementation defined attribute 'IMG, which can >>>> do as it pleases. The Ada type attribute 'Image >>>> takes a value of type Positive'Base, which includes 0, >>>> which is why outputting 0 is perfectly fine. >>>> >>>> (It's not a subtype attribute, but a type attribute, >>>> if this makes sense.) >>> >>> The issue here is not whether or not 'img fails but the fact that V is returned with a value out of range. >> >> The issue is rather, I think, whether V is returned at all. >> There would have to be an assignment within the null procedure. >> > Which could be a case if the compiler used copy-in/copy-out semantics > for scalars (or just copy-out for the test sample). GNAT, if I recall, uses > reference semantics, Then GNAT would be in violation of the Ada standard -- see RM 6.2(3/3). I hope and believe that is not the case... -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 11:44 ` Dennis Lee Bieber 2016-04-06 20:41 ` Niklas Holsti @ 2016-04-06 20:54 ` Randy Brukardt 1 sibling, 0 replies; 91+ messages in thread From: Randy Brukardt @ 2016-04-06 20:54 UTC (permalink / raw) "Dennis Lee Bieber" <wlfraed@ix.netcom.com> wrote in message news:c7t9gb1972nrm7e64hudekqvi5pmldtm17@4ax.com... ... >>The issue is rather, I think, whether V is returned at all. >>There would have to be an assignment within the null procedure. >> > Which could be a case if the compiler used copy-in/copy-out semantics > for scalars (or just copy-out for the test sample). GNAT, if I recall, > uses > reference semantics, and as out-only wouldn't be checking the initial > value > on entry. Scalars in Ada are always by-copy, so the *effect* always have to be copy-in/copy-out, regardless of how that's implemented. (I can't speak for GNAT, but Janus/Ada makes copies at the call-site if we want to/need to use by-reference parameter passing.) The rules for whether an out parameter is initialized (and if so, how) are complicated - see 6.4.1(12-15). 6.4.1(15) most likely applies in this case (assuming no Default_Value aspect is involved), and that says that the value is uninitialized. And of course the value of an uninitialized object can be anything. Randy. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 10:17 ` G.B. 2016-04-06 11:44 ` Dennis Lee Bieber @ 2016-04-06 20:47 ` Randy Brukardt 2016-04-06 21:01 ` Randy Brukardt 1 sibling, 1 reply; 91+ messages in thread From: Randy Brukardt @ 2016-04-06 20:47 UTC (permalink / raw) "G.B." <bauhaus@futureapps.invalid> wrote in message news:ne2ngo$uea$1@dont-email.me... > On 06.04.16 10:19, ahlan@marriott.org wrote: ... >> But even that is not the point I'm trying to make. >> I am suggesting that it ought not to be possible to define a null >> procedure >> that has out parameters without some form of warning being issued. > > I think the usual answer is that the compiler is not a mind > reader and the best you could get is a warning. Who knows? > Maybe the technical requirements are such that the programmer > uses a procedure like Test as a placeholder, maybe its existence > is dictated by an abstract type, maybe a null procedure really > should do nothing at all, which includes not touching V. I agree with Georg here. It *seems* like checks like the one Ahlan is suggesting are a good idea, until you trip over one. (The check in Ada that every function have at least one return is a similar idea, which causes no end of trouble.) I can think of at least three reasons why one might write a null procedure with an out parameter: (1) The null procedure body is a TBD placeholder. It will be replaced with a real body at some future point, but we still want to compile. (2) The out parameter isn't used for some implementations. This often comes up when there are multiple parameters. (We ran into this commonly in Claw, although we usually used in out parameters in such cases to avoid de-initializing objects.) The situation is that some objects need additional return information and others don't: procedure Do_Something (Obj : in out Object; Result : in out Result_Type; Extra_Info : out Natural); Extra_Info is only used if Result has a particular value. (3) The null procedure is used in an interface. In that case, giving a body isn't possible. I think you could make a case that all of these are better written some other way, but that's irrelevant, in that each of these could happen in real code, and making a legality check would break that code. (Thus, making it illegal would probably be considered too incompatible for future Ada, unless of course we discovered some semantic problem that doing that would fix.) The Ada Standard has nothing to say about warnings (other than for pragmas). Perhaps some future version of Ada will change that, but as of now, every warning is implementation-defined, and thus it they don't have anything to do with the language. (That is, talk to your vendor about warnings.) Randy. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 20:47 ` Randy Brukardt @ 2016-04-06 21:01 ` Randy Brukardt 2016-04-06 21:22 ` Dmitry A. Kazakov 0 siblings, 1 reply; 91+ messages in thread From: Randy Brukardt @ 2016-04-06 21:01 UTC (permalink / raw) I said: > It *seems* like checks like the one Ahlan is suggesting are a good idea, > until you trip over one. (The check in Ada that every function have at > least one return is a similar idea, which causes no end of trouble.) On top of that, exactly what would the check be? Which of the following ought to be illegal? procedure Foo1 (Obj : out Positive) is null; procedure Foo2 (Obj : out Positive) is begin null; end Foo2; Debug : constant Boolean := False; procedure Foo3 (Obj : out Positive) is begin if Debug then Put_Line ("Foo3 called"); end if; end Foo3; Foo1 and Foo2 are semantically identical (Foo1 is in fact defined in terms of Foo2). But it is clearly a lot harder for an Ada compiler to detect Foo2 compared to Foo1 (and changing between them is common). Having different legality for Foo1 and Foo2 would be annoying at best. Obviously, detecting Foo3 is even harder for a compiler, but again, semantically it is identical to Foo2. So where do you stop? And why? Randy. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 21:01 ` Randy Brukardt @ 2016-04-06 21:22 ` Dmitry A. Kazakov 2016-04-07 7:27 ` Randy Brukardt 0 siblings, 1 reply; 91+ messages in thread From: Dmitry A. Kazakov @ 2016-04-06 21:22 UTC (permalink / raw) On 2016-04-06 23:01, Randy Brukardt wrote: > I said: >> It *seems* like checks like the one Ahlan is suggesting are a good idea, >> until you trip over one. (The check in Ada that every function have at >> least one return is a similar idea, which causes no end of trouble.) > > On top of that, exactly what would the check be? Which of the following > ought to be illegal? > > procedure Foo1 (Obj : out Positive) is null; > > procedure Foo2 (Obj : out Positive) is > begin > null; > end Foo2; > > Debug : constant Boolean := False; > procedure Foo3 (Obj : out Positive) is > begin > if Debug then > Put_Line ("Foo3 called"); > end if; > end Foo3; > > Foo1 and Foo2 are semantically identical (Foo1 is in fact defined in terms > of Foo2). But it is clearly a lot harder for an Ada compiler to detect Foo2 > compared to Foo1 (and changing between them is common). Having different > legality for Foo1 and Foo2 would be annoying at best. > > Obviously, detecting Foo3 is even harder for a compiler, but again, > semantically it is identical to Foo2. So where do you stop? And why? Simple, the rules must be same as ones for the function return, which are exemplarily annoying, nevertheless considered OK. To the question "where to stop" there is a simple rule: no false negatives Thus is you want to stop at Foo3, the outcome is "illegal" regardless Debug value. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 21:22 ` Dmitry A. Kazakov @ 2016-04-07 7:27 ` Randy Brukardt 0 siblings, 0 replies; 91+ messages in thread From: Randy Brukardt @ 2016-04-07 7:27 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:ne3un4$5qf$1@gioia.aioe.org... ... > Simple, the rules must be same as ones for the function return, which are > exemplarily annoying, nevertheless considered OK. Umm, no, they're not considered "OK". We don't feel comfortable removing the function return Legality Rule (some people view that as moving to a less safe version of Ada), but we surely don't want any more like that. (We've learned our lesson, I hope.) Randy. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-05 12:02 Uninitialized out parameters ahlan 2016-04-05 13:17 ` rieachus 2016-04-05 16:19 ` G.B. @ 2016-04-06 11:37 ` AdaMagica 2016-04-06 13:44 ` ahlan 2 siblings, 1 reply; 91+ messages in thread From: AdaMagica @ 2016-04-06 11:37 UTC (permalink / raw) Hm, from the point of view of the RM, the RM has nothing to say about warnings - only whether the code is legal or illegal. So giving warnings is up to the compiler. Now for scalar variables, the RM says, in mode variables are copied in, out mode variables are copied out, in out variables are both. So as I understand, even a null procedure with an out parameter does something to the parameter: it copies out an uninitialized variable (which can have any value whatsoever). Language lawyers - please? ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 11:37 ` AdaMagica @ 2016-04-06 13:44 ` ahlan 2016-04-06 14:09 ` Mark Lorenzen ` (2 more replies) 0 siblings, 3 replies; 91+ messages in thread From: ahlan @ 2016-04-06 13:44 UTC (permalink / raw) On Wednesday, April 6, 2016 at 1:37:41 PM UTC+2, AdaMagica wrote: > Hm, from the point of view of the RM, the RM has nothing to say about warnings - only whether the code is legal or illegal. So giving warnings is up to the compiler. > > Now for scalar variables, the RM says, in mode variables are copied in, out mode variables are copied out, in out variables are both. So as I understand, even a null procedure with an out parameter does something to the parameter: it copies out an uninitialized variable (which can have any value whatsoever). Language lawyers - please? In the annotated RM, in the section concerning Null Procedures, it says "There are no null functions because the return value has to be constructed somehow; a function that always raises Program_Error doesn't seem very useful or worth the complication" If there are no null functions because a return value has to be constructed then surely the same applies to null procedures that have out parameters. These too should be prohibited because they too require that a value has to be constructed. If not prohibited then at least Program_Error should be raised and ideally a warning is generated by the compiler warning that calling the null procedure will always raise Program_Error. Currently GNAT simply returns "something" - zero or null that sometimes escapes detection. This is NOT desirable. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 13:44 ` ahlan @ 2016-04-06 14:09 ` Mark Lorenzen 2016-04-06 14:10 ` G.B. 2016-04-06 20:53 ` Stefan.Lucks 2 siblings, 0 replies; 91+ messages in thread From: Mark Lorenzen @ 2016-04-06 14:09 UTC (permalink / raw) On Wednesday, April 6, 2016 at 3:44:08 PM UTC+2, ah...@marriott.org wrote: > If there are no null functions because a return value has to be constructed then surely the same applies to null procedures that have out parameters. These too should be prohibited because they too require that a value has to be constructed. If not prohibited then at least Program_Error should be raised and ideally a warning is generated by the compiler warning that calling the null procedure will always raise Program_Error. > Currently GNAT simply returns "something" - zero or null that sometimes escapes detection. This is NOT desirable. It would of course be useful if GNAT would issue a warning, but it would only solve the (somewhat conceived) example of a null procedure with an out parameter. There are more interesting situations where an out parameter or variable may end up having an undefined value. If you want to write bullet-proff software you should maybe have a look at the SPARK 2014 subset of Ada and the related tools (GNATprove). Anyway, you can suggest to AdaCore that GNAT should issue a warning in your example. Regards, Mark L ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 13:44 ` ahlan 2016-04-06 14:09 ` Mark Lorenzen @ 2016-04-06 14:10 ` G.B. 2016-04-06 20:53 ` Stefan.Lucks 2 siblings, 0 replies; 91+ messages in thread From: G.B. @ 2016-04-06 14:10 UTC (permalink / raw) On 06.04.16 15:44, ahlan@marriott.org wrote: > If there are no null functions because a return value has to be constructed then surely the same applies to null procedures that have out parameters. These too should be prohibited because they too require that a value has to be constructed. Arguably, procedures do not need to construct a value for an out parameter whenever they do not assign any: the actual parameter is allocated already, whether it is initialized or not. Does the RM require an assignment happening as part of the call? ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 13:44 ` ahlan 2016-04-06 14:09 ` Mark Lorenzen 2016-04-06 14:10 ` G.B. @ 2016-04-06 20:53 ` Stefan.Lucks 2016-04-06 21:03 ` Randy Brukardt ` (3 more replies) 2 siblings, 4 replies; 91+ messages in thread From: Stefan.Lucks @ 2016-04-06 20:53 UTC (permalink / raw) [-- Attachment #1: Type: text/plain, Size: 1571 bytes --] On Wed, 6 Apr 2016, ahlan@marriott.org wrote: > In the annotated RM, in the section concerning Null Procedures, it says > "There are no null functions because the return value has to be > constructed somehow; a function that always raises Program_Error doesn't > seem very useful or worth the complication" If there are no null > functions because a return value has to be constructed then surely the > same applies to null procedures that have out parameters. These too > should be prohibited [...] This seems to be right. It does not make much sense to allow the declaration of procedure X(Formal: out T) is null; while prohibiting the declaration of function Y return R is null; The point is, you can neither call X nor Y. Semantically, both statements X(Actual); Actual := Y; are equally useless, or at least their effect is equally undefined. Allowing the declaration of X, but prohibiting the declaration of Y is inconsistent. If people really think they need to declare something like the above procedure X, a revised Ada standard could allow declarations such as procedure X(Formal: T) is raise; and function Y return T is raise; where "is raise" stands for "raise Program_Error". That may sometimes come handy in the context of inheritance, or so. -------- I love the taste of Cryptanalysis in the morning! -------- www.uni-weimar.de/de/medien/professuren/mediensicherheit/people/stefan-lucks ----Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany---- ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 20:53 ` Stefan.Lucks @ 2016-04-06 21:03 ` Randy Brukardt 2016-04-06 21:12 ` Niklas Holsti ` (2 subsequent siblings) 3 siblings, 0 replies; 91+ messages in thread From: Randy Brukardt @ 2016-04-06 21:03 UTC (permalink / raw) [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain, Size: 1617 bytes --] <Stefan.Lucks@uni-weimar.de> wrote in message news:alpine.DEB.2.20.1604062240350.29458@debian... On Wed, 6 Apr 2016, ahlan@marriott.org wrote: > In the annotated RM, in the section concerning Null Procedures, it says > "There are no null functions because the return value has to be > constructed somehow; a function that always raises Program_Error doesn't > seem very useful or worth the complication" If there are no null > functions because a return value has to be constructed then surely the > same applies to null procedures that have out parameters. These too > should be prohibited [...] This seems to be right. It does not make much sense to allow the declaration of procedure X(Formal: out T) is null; while prohibiting the declaration of function Y return R is null; The point is, you can neither call X nor Y. Semantically, both statements X(Actual); Actual := Y; are equally useless, or at least their effect is equally undefined. Allowing the declaration of X, but prohibiting the declaration of Y is inconsistent. If people really think they need to declare something like the above procedure X, a revised Ada standard could allow declarations such as procedure X(Formal: T) is raise; and function Y return T is raise; where "is raise" stands for "raise Program_Error". That may sometimes come handy in the context of inheritance, or so. -------- I love the taste of Cryptanalysis in the morning! -------- www.uni-weimar.de/de/medien/professuren/mediensicherheit/people/stefan-lucks ----Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany---- ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 20:53 ` Stefan.Lucks 2016-04-06 21:03 ` Randy Brukardt @ 2016-04-06 21:12 ` Niklas Holsti 2016-04-06 21:30 ` Randy Brukardt 2016-04-07 7:52 ` Georg Bauhaus 3 siblings, 0 replies; 91+ messages in thread From: Niklas Holsti @ 2016-04-06 21:12 UTC (permalink / raw) On 16-04-06 23:53 , Stefan.Lucks@uni-weimar.de wrote: > On Wed, 6 Apr 2016, ahlan@marriott.org wrote: > >> In the annotated RM, in the section concerning Null Procedures, it >> says "There are no null functions because the return value has to be >> constructed somehow; a function that always raises Program_Error >> doesn't seem very useful or worth the complication" If there are no >> null functions because a return value has to be constructed then >> surely the same applies to null procedures that have out parameters. >> These too should be prohibited [...] > > This seems to be right. It does not make much sense to allow the > declaration of > > procedure X(Formal: out T) is null; If T has default initialization (which is now possible even for scalars, with the Default_Value aspect), that seems reasonable to me. It is equivalent to having "is begin null; end X;" as the body, which has a well-defined effect when there is a Default_Value, by RM 6.4.1(13.1/4) and other paragraphs in 6.4.1. > while prohibiting the declaration of > > function Y return R is null; For a function, a null body is illegal (no "return" statement). Ok, that's a nit-pick; without that rule, this could be as defined as X, under the same circumstances. > The point is, you can neither call X nor Y. Semantically, both statements > > X(Actual); > Actual := Y; > > are equally useless, or at least their effect is equally undefined. Not undefined in the case of X, when the type has a default value. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 20:53 ` Stefan.Lucks 2016-04-06 21:03 ` Randy Brukardt 2016-04-06 21:12 ` Niklas Holsti @ 2016-04-06 21:30 ` Randy Brukardt 2016-04-07 9:56 ` Stefan.Lucks 2016-04-07 7:52 ` Georg Bauhaus 3 siblings, 1 reply; 91+ messages in thread From: Randy Brukardt @ 2016-04-06 21:30 UTC (permalink / raw) <Stefan.Lucks@uni-weimar.de> wrote in message news:alpine.DEB.2.20.1604062240350.29458@debian... On Wed, 6 Apr 2016, ahlan@marriott.org wrote: >> In the annotated RM, in the section concerning Null Procedures, it says >> "There are no null functions because the return value has to be >> constructed somehow; a function that always raises Program_Error doesn't >> seem very useful or worth the complication" If there are no null >> functions because a return value has to be constructed then surely the >> same applies to null procedures that have out parameters. These too >> should be prohibited [...] > >This seems to be right. It does not make much sense to allow the >declaration of > > procedure X(Formal: out T) is null; > >while prohibiting the declaration of > > function Y return R is null; Playing Devil's Advocate here, the latter always raises Program_Error; if you really meant that there are better ways (see below). The former does nothing at all other than deinitialize its actual parameter. So they're not really the same thing. > The point is, you can neither call X nor Y. Semantically, both statements > > X(Actual); > Actual := Y; > >are equally useless, or at least their effect is equally undefined. No, both are very well-defined. And there is nothing wrong in either case with making a call (so long as Actual is not used afterwards. I have *lots* of procedures for which one or more actuals are meaningless after the call, and better not be touched. (The case where *all* parameters are like that is of course pathological, but to have one of of several is pretty common.) >Allowing the declaration of X, but prohibiting the declaration of Y is >inconsistent. Maybe, but there is a big difference: allowing the declaration of Y is new feature that would be a lot of work for implementers and is 100% useless. (Again, there is a better way to write a function that always raises Program_Error, see below.) Whereas *disallowing* the declaration of X would be additional work for implementers (and now would also be incompatible). The null procedure feature itself has many obvious uses, and you are talking about a tiny corner case. I can see that it might have made sense to disallow out parameters when the feature was defined, but I don't think we ever thought of it. As I noted in another message, a null procedure is semantically just a short-hand for "begin null; end;" and I don't think we considered having *different* Legality Rules for it. And it's definitely too late now; breaking existing code (especially interface declarations) for this issue seems like a non-starter. Such a rule would do very little to reduce this problem (it happens to me periodically for normal procedures), so the incompatibility would just not be tolerable. And of course, changing the rules to raise Program_Error, as the OP suggested, would be even more of a nonstarter as a runtime incompatibility. No one would want programs that work fine today start raising Program_Error because some object that is never used got de-initialized. We had a similar case that involved a real semantic problem with access types, and we eventually decided to make it illegal (rather than raise Program_Error or make it erroneous) as the best of a bad set of choices (Program_Error was the least liked of all). [We did choose Program_Error for a similar case, but that was because we assumed that there were no such programs as "scalar with Default_Value" was first added in Ada 2012, not so for things in Ada 83 (or Ada 2005).] Ada 83 got the handling of uninitialized objects wrong (including this case of out parameters) for a language which defaults to "safe". We're pretty much stuck with that today, changes would break almost all existing code. That's too bad, but I guess it just shows that no language is perfect. >If people really think they need to declare something like the above >procedure X, a revised Ada standard could allow declarations such as > > procedure X(Formal: T) is raise; > >and > > function Y return T is raise; > >where "is raise" stands for "raise Program_Error". That may sometimes come >handy in the context of inheritance, or so. (1) The above null procedure X does not and would never raise Program_Error, so the first part of this doesn't make any sense. (2) The latter can be written in current Ada 2012: (that is, with TC1 implemented) function Y return T is (raise Program_Error); which is both clearer and hardly any longer. I can't imagine why we'd add another feature just to save two parens and a name (that it actually helps to make explicit). Randy. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 21:30 ` Randy Brukardt @ 2016-04-07 9:56 ` Stefan.Lucks 2016-04-07 16:08 ` AdaMagica 0 siblings, 1 reply; 91+ messages in thread From: Stefan.Lucks @ 2016-04-07 9:56 UTC (permalink / raw) [-- Attachment #1: Type: text/plain, Size: 1658 bytes --] On Wed, 6 Apr 2016, Randy Brukardt wrote: > <Stefan.Lucks@uni-weimar.de> wrote in message > news:alpine.DEB.2.20.1604062240350.29458@debian... > On Wed, 6 Apr 2016, ahlan@marriott.org wrote: >> procedure X(Formal: T) is raise; >> >> and >> >> function Y return T is raise; >> >> where "is raise" stands for "raise Program_Error". That may sometimes come >> handy in the context of inheritance, or so. > > (1) The above null procedure X does not and would never raise Program_Error, > so the first part of this doesn't make any sense. The OP suggested change the semantic and raise Programm_Error for the above null procedure. I just suggested a possible syntax if you really want to indicate "this is not yet implemented and will raise an exception if you dare calling it." On the other hand, the existing Ada 2012 syntax will *almost* serve that purpose. procedure X(Formal: out T) is null with pre => False; -- Procedure X will be implemented in a forthcoming update. -- Until then, don't even think of calling it! Alas, this seems only to work if T is tagged and the aspect is "pre'class", rather than plain "pre". > (2) The latter can be written in current Ada 2012: (that is, with TC1 > implemented) > function Y return T is (raise Program_Error); Great! I wasn't aware of that. I always thought, the expression in brackets had to be of type T. Stefan -------- I love the taste of Cryptanalysis in the morning! -------- www.uni-weimar.de/de/medien/professuren/mediensicherheit/people/stefan-lucks ----Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany---- ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-07 9:56 ` Stefan.Lucks @ 2016-04-07 16:08 ` AdaMagica 2016-04-07 23:02 ` Randy Brukardt 0 siblings, 1 reply; 91+ messages in thread From: AdaMagica @ 2016-04-07 16:08 UTC (permalink / raw) Am Donnerstag, 7. April 2016 11:57:02 UTC+2 schrieb Stefan...@uni-weimar.de: > > (2) The latter can be written in current Ada 2012: (that is, with TC1 > > implemented) > > function Y return T is (raise Program_Error); > > Great! I wasn't aware of that. I always thought, the expression in > brackets had to be of type T. > > Stefan A raise_expression matches any type. See RM. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-07 16:08 ` AdaMagica @ 2016-04-07 23:02 ` Randy Brukardt 2016-04-08 7:32 ` Dmitry A. Kazakov 0 siblings, 1 reply; 91+ messages in thread From: Randy Brukardt @ 2016-04-07 23:02 UTC (permalink / raw) "AdaMagica" <christ-usch.grein@t-online.de> wrote in message news:51041ba8-3243-46bc-b97d-b106d4b357e2@googlegroups.com... > Am Donnerstag, 7. April 2016 11:57:02 UTC+2 schrieb > Stefan...@uni-weimar.de: > >> > (2) The latter can be written in current Ada 2012: (that is, with TC1 >> > implemented) >> > function Y return T is (raise Program_Error); >> >> Great! I wasn't aware of that. I always thought, the expression in >> brackets had to be of type T. >> >> Stefan > > A raise_expression matches any type. See RM. Right. One can think of it sort of like "bottom" in a functional language - it represents the "not a value" of any type. (And touch it and you die.) OTOH, like me, you may not want to think of functional languages much. ;-) Randy. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-07 23:02 ` Randy Brukardt @ 2016-04-08 7:32 ` Dmitry A. Kazakov 0 siblings, 0 replies; 91+ messages in thread From: Dmitry A. Kazakov @ 2016-04-08 7:32 UTC (permalink / raw) On 08/04/2016 01:02, Randy Brukardt wrote: > "AdaMagica" <christ-usch.grein@t-online.de> wrote in message > news:51041ba8-3243-46bc-b97d-b106d4b357e2@googlegroups.com... >> Am Donnerstag, 7. April 2016 11:57:02 UTC+2 schrieb >> Stefan...@uni-weimar.de: >> >>>> (2) The latter can be written in current Ada 2012: (that is, with TC1 >>>> implemented) >>>> function Y return T is (raise Program_Error); >>> >>> Great! I wasn't aware of that. I always thought, the expression in >>> brackets had to be of type T. >>> >>> Stefan >> >> A raise_expression matches any type. See RM. > > Right. One can think of it sort of like "bottom" in a functional language - > it represents the "not a value" of any type. (And touch it and you die.) > > OTOH, like me, you may not want to think of functional languages much. ;-) Yes, better think it typed! It is same as an IEEE float which values are real U {NaN, +Inf, -Inf}. Propagating exceptions is a sort of value. In function Y return T is (raise Program_Error); we assume that T consists of values of T values and exceptions of all sorts. That is weakly typed, a bit. But it also a way how to spell Y's post-condition: "T or Program_Error raised" could be a type Y returns. That would make an implementation (raise Constraint_Error) illegal. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters. 2016-04-06 20:53 ` Stefan.Lucks ` (2 preceding siblings ...) 2016-04-06 21:30 ` Randy Brukardt @ 2016-04-07 7:52 ` Georg Bauhaus 3 siblings, 0 replies; 91+ messages in thread From: Georg Bauhaus @ 2016-04-07 7:52 UTC (permalink / raw) On 06/04/16 22:53, Stefan.Lucks@uni-weimar.de wrote: > If people really think they need to declare something like the above procedure X, a revised Ada standard could allow declarations such as > > procedure X(Formal: T) is raise; > > and > > function Y return T is raise; > > where "is raise" stands for "raise Program_Error". That may sometimes come handy in the context of inheritance, or so. Two prominent use cases will suggest this hammer won't fly ;-) if used as a replacement: 1. Testing, or integration builds at various incomplete stages: one couldn't test part B of a program if part A of the program, calling X, always raises before it gets to B. 2. OPENSTEP style programming (a.k.a. Cocoa) as an example, meaning that, conceptually, whenever an object is not (yet) defined (nil), but then receives a message, nothing happens. So, if a procedure does nothing and out comes nothing, then it doesn't do harm either, at least if programmers know what to expect. They fill in the blanks later. I'd rather accept null functions in the set of oddities of Ada than be forced to always have finished everything. Note that raising disallows stubs like procedure X (Formal : out T) is begin pragma Warning ("TODO: compute a value for out Formal!") null; end X; Treating warnings as errors should help with strict rejection rules where the projects demand them. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized out parameters @ 1996-07-29 0:00 W. Wesley Groleau (Wes) 0 siblings, 0 replies; 91+ messages in thread From: W. Wesley Groleau (Wes) @ 1996-07-29 0:00 UTC (permalink / raw) Bob Duff pointed out that in Ada, OFTEN the compiler cannot tell whether a variable has been initialized and suggested that giving warnings in these cases are a big pain. (They're worse than a pain if they induce programmers to turn off all warnings.) Sometimes, the only reason the compiler can't tell is due to separate compilation. Another thread has already beat to death the reason why this is not true of GNAT. If you're not using gnat, independent tools do exist that can change the "unknown" to "correct" or "wrong" in many cases. How about having a compiler make an optional SINGLE warning for each invokation something like: COMPILER WAS UNABLE TO DETERMINE WHETHER THE FOLLOWING ITEMS WERE INITIALIZED BEFORE BEING REFERENCED: Identifier File Line No. ---------------------------- ---------------------------------- -------- PKG.PROC.PROC.VRBL.FIELD some_ada_source_file.ada 65,736 ..... Yes, go ahead and use this example to justify putting thousands of lines in a source file. NOT! :-) --------------------------------------------------------------------------- W. Wesley Groleau (Wes) Office: 219-429-4923 Magnavox - Mail Stop 10-40 Home: 219-471-7206 Fort Wayne, IN 46808 elm (Unix): wwgrol@pseserv3.fw.hac.com --------------------------------------------------------------------------- ^ permalink raw reply [flat|nested] 91+ messages in thread
* Uninitialized "out" parameters @ 1996-07-18 0:00 Paul Whittington 1996-07-18 0:00 ` Adam Beneschan ` (5 more replies) 0 siblings, 6 replies; 91+ messages in thread From: Paul Whittington @ 1996-07-18 0:00 UTC (permalink / raw) In the following Ada program, should either the compiler or the run-time get some kind of error because the out parameter is not initialized? procedure Testit is procedure SubP (op : out Integer) is begin op := op+1; end SubP; I : Integer; begin SubP (I); end Testit; ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-18 0:00 Uninitialized "out" parameters Paul Whittington @ 1996-07-18 0:00 ` Adam Beneschan 1996-07-18 0:00 ` Robert Dewar ` (3 more replies) 1996-07-18 0:00 ` Robert Dewar ` (4 subsequent siblings) 5 siblings, 4 replies; 91+ messages in thread From: Adam Beneschan @ 1996-07-18 0:00 UTC (permalink / raw) Paul Whittington <paul@sage.inel.gov> writes: >In the following Ada program, should either the compiler or the run-time >get some kind of error because the out parameter is not initialized? > >procedure Testit is > > procedure SubP (op : out Integer) is > begin > op := op+1; > end SubP; > > I : Integer; > >begin > SubP (I); >end Testit; Well, you can't read an "out" parameter at all, so it's illegal to use "op" in the right-hand side of your assignment. So the compiler should give you an error. Also, in Ada83, you'll get an error because I needs to be declared before the code for SubP appears. If you change op to an "in out" parameter, you'll be reading an uninitialized variable, but typically neither the compiler nor the runtime will complain. -- Adam ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-18 0:00 ` Adam Beneschan @ 1996-07-18 0:00 ` Robert Dewar 1996-07-19 0:00 ` Dale Stanbrough ` (2 subsequent siblings) 3 siblings, 0 replies; 91+ messages in thread From: Robert Dewar @ 1996-07-18 0:00 UTC (permalink / raw) Adam said "Well, you can't read an "out" parameter at all, so it's illegal to use "op" in the right-hand side of your assignment. So the compiler should give you an error. Also, in Ada83, you'll get an error because I needs to be declared before the code for SubP appears. If you change op to an "in out" parameter, you'll be reading an uninitialized variable, but typically neither the compiler nor the runtime will complain." That's quite wrong, you can definitely read out parameters in Ada. (this is a new feature, you couldn't read out parameters in Ada 83, which explains Adam's mistake). Anyway, an Ada compiler definitely must NOT give an error for this program (it may give a warning). ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-18 0:00 ` Adam Beneschan 1996-07-18 0:00 ` Robert Dewar @ 1996-07-19 0:00 ` Dale Stanbrough 1996-07-19 0:00 ` James A. Squire 1996-07-19 0:00 ` Adam Beneschan 1996-07-19 0:00 ` Samuel Tardieu 1996-07-19 0:00 ` Pascal Obry 3 siblings, 2 replies; 91+ messages in thread From: Dale Stanbrough @ 1996-07-19 0:00 UTC (permalink / raw) Adam Beneschan writes: "Well, you can't read an "out" parameter at all, so it's illegal to use "op" in the right-hand side of your assignment. So the compiler should give you an error. Also, in Ada83, you'll get an error because I needs to be declared before the code for SubP appears. If you change op to an "in out" parameter, you'll be reading an uninitialized variable, but typically neither the compiler nor the runtime will complain." Ada95 does allow you to read out parameters. The code written simply uses an uninitialized variable, and I would imagine it would be declared erroneous by the LRM. Dale ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-19 0:00 ` Dale Stanbrough @ 1996-07-19 0:00 ` James A. Squire 1996-07-19 0:00 ` Adam Beneschan 1996-07-20 0:00 ` Michael Feldman 1996-07-19 0:00 ` Adam Beneschan 1 sibling, 2 replies; 91+ messages in thread From: James A. Squire @ 1996-07-19 0:00 UTC (permalink / raw) Adam Beneschan wrote: > > Dale Stanbrough <dale@goanna.cs.rmit.edu.au> writes: > > >Adam Beneschan writes: > >"Well, you can't read an "out" parameter at all, so it's illegal to use > > "op" in the right-hand side of your assignment. So the compiler > > should give you an error. Also, in Ada83, you'll get an error because > > I needs to be declared before the code for SubP appears. > > > > If you change op to an "in out" parameter, you'll be reading an > > uninitialized variable, but typically neither the compiler nor the > > runtime will complain." > > > > > >Ada95 does allow you to read out parameters. The code written simply > >uses an uninitialized variable, and I would imagine it would be declared > >erroneous by the LRM. > > Sorry, I wasn't aware of this change. > > This rule change frightens me a little. In the posted example: > > procedure SubP (op : out integer) is > begin > op := op + 1; > end SubP; > > I've been known to accidentally type "out" when I mean "in out". In > Ada 83, the compiler would catch me, but now it won't, and the effect > will be very different because here the "op" on the right side of the > assignment is always uninitialized. However, I guess a smart compiler > would let me know that I'm using an uninitialized parameter, and > perhaps the advantages of letting you read an OUT parameter after > you've written to it outweigh this disadvantage. I tried to find out from the LRM if this compiler behavior is required, but I don't see it anywher in chapter 6. I do know that in 6.1.1 of the Ada95 Rationale, it has the following paragraph: "For Ada 95, we have removed the restrictions on the use of out parameters. Specifying that a formal parameter is of mode out indicates that the caller need not initialize it prior to the call. However, within the procedure, once the ^^^^^^^^ parameter has been initialized, it may be read and updated like any other ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ variable. As with a normal variable, it is an error to depend on the value of an out parameter prior to its being initialized." but I don't know if that's a compiler error or a run-time error. From the context, I'd guess a run-time error. -- James Squire mailto:ja_squire@csehp3.mdc.com MDA Avionics Tools & Processes McDonnell Douglas Aerospace http://www.mdc.com/ Opinions expressed here are my own and NOT my company's "Nice shark...pretty shark..." -- Londo, "The Gathering" ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-19 0:00 ` James A. Squire @ 1996-07-19 0:00 ` Adam Beneschan 1996-07-20 0:00 ` Michael Feldman 1 sibling, 0 replies; 91+ messages in thread From: Adam Beneschan @ 1996-07-19 0:00 UTC (permalink / raw) "James A. Squire" <m193884@CSEHP3.MDC.COM> writes: >Adam Beneschan wrote: >> >> This rule change frightens me a little. In the posted example: >> >> procedure SubP (op : out integer) is >> begin >> op := op + 1; >> end SubP; >> >> I've been known to accidentally type "out" when I mean "in out". In >> Ada 83, the compiler would catch me, but now it won't, and the effect >> will be very different because here the "op" on the right side of the >> assignment is always uninitialized. However, I guess a smart compiler >> would let me know that I'm using an uninitialized parameter, and >> perhaps the advantages of letting you read an OUT parameter after >> you've written to it outweigh this disadvantage. > >I tried to find out from the LRM if this compiler behavior is required, >but I don't see it anywher in chapter 6. I'm not sure what you're referring to by "this" compiler behavior--whether you mean that it treats "op" as uninitialized, or whether you're referring to giving a warning about using an uninitialized parameter. The first is covered by 6.4.1(12-15): "For an out parameter that is passed by copy, the format parameter object is created, and: . . ." "For any other type [besides access types and certain composite types], the formal parameter is uninitialized. . . ." >I do know that in 6.1.1 of the >Ada95 Rationale, it has the following paragraph: > >"For Ada 95, we have removed the restrictions on the use of out >parameters. Specifying that a formal parameter is of mode out indicates >that the caller need not initialize it prior to the call. However, >within the procedure, once the > ^^^^^^^^ >parameter has been initialized, it may be read and updated like any >other >^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >variable. As with a normal variable, it is an error to depend on the >value of an out parameter prior to its being initialized." > >but I don't know if that's a compiler error or a run-time error. From >the context, I'd guess a run-time error. I'd guess it's the same as for any uninitialized object, which is a bounded error that most likely won't be caught. -- Adam ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-19 0:00 ` James A. Squire 1996-07-19 0:00 ` Adam Beneschan @ 1996-07-20 0:00 ` Michael Feldman 1996-07-21 0:00 ` Fergus Henderson 1 sibling, 1 reply; 91+ messages in thread From: Michael Feldman @ 1996-07-20 0:00 UTC (permalink / raw) In article <31EF9DFC.6FB4@csehp3.mdc.com>, James A. Squire <m193884@CSEHP3.MDC.COM> wrote: [quoting the Rationale] >variable. As with a normal variable, it is an error to depend on the >value of an out parameter prior to its being initialized." then commenting: > >but I don't know if that's a compiler error or a run-time error. From >the context, I'd guess a run-time error. It _cannot_ be a compiler error, because in general it is undecidable whether a variable is used before it is initialized. A friendly compiler can give a compilation _warning_. Now, will it be a runtime error? That is, will it cause an exception to be raised? Maybe. This is a special case - as the Rationale mentioned - of an ordinary uninitialized variable. We must assume that an uninitialized variable has an arbitrary value, which may or may not be in range. We've had recurring threads on this issue in this newsgroup. That the uninitialized object happens to be an OUT parameter doesn;t change anything. Mike Feldman ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-20 0:00 ` Michael Feldman @ 1996-07-21 0:00 ` Fergus Henderson 1996-07-21 0:00 ` Michael Feldman 0 siblings, 1 reply; 91+ messages in thread From: Fergus Henderson @ 1996-07-21 0:00 UTC (permalink / raw) mfeldman@seas.gwu.edu (Michael Feldman) writes: >It _cannot_ be a compiler error, because in general it is undecidable >whether a variable is used before it is initialized. Sure it could be a compiler error. I know of at least one language for which that is the case, and there are probably others. (I'm not sure, but Java may be one of them?) Note that type correctness (defined in the dynamic sense) is also undecidable -- yet there are certainly *lots* of languages for which the compiler enforces type safety at compile time. -- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit" PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-21 0:00 ` Fergus Henderson @ 1996-07-21 0:00 ` Michael Feldman 1996-07-21 0:00 ` Robert Dewar 1996-07-22 0:00 ` Fergus Henderson 0 siblings, 2 replies; 91+ messages in thread From: Michael Feldman @ 1996-07-21 0:00 UTC (permalink / raw) In article <4ssn9r$p6e@mulga.cs.mu.OZ.AU>, Fergus Henderson <fjh@mundook.cs.mu.OZ.AU> wrote: >mfeldman@seas.gwu.edu (Michael Feldman) writes: > >>It _cannot_ be a compiler error, because in general it is undecidable >>whether a variable is used before it is initialized. > >Sure it could be a compiler error. I know of at least one language >for which that is the case, and there are probably others. >(I'm not sure, but Java may be one of them?) I'm not sure about Java either, but you quoted me out of context; we were talking about Ada, in which there is no _required_ initialization of variables. In that context, my statement is correct. If the language rules required that each variable must be initialized at elaboration (say, either by an initialization expression or by default using some value within the type of that variable), then there would be no uninitialized-variable problem because all variables were guaranteed to be initialized. > >Note that type correctness (defined in the dynamic sense) is also >undecidable -- yet there are certainly *lots* of languages for which >the compiler enforces type safety at compile time. That is a different issue. If Ada _compelled_ initialization, it would be trivial to determine whether all variables were initialized. Certainly the compiler could "enforce" initialization; if you failed to supply an initializer, the compiler would supply a default. There have been earlier threads on why Ada does not compel initialization. This is NOT what we were talking about. The thread was about Ada as it is, not as we might like it to be. Given that Ada does _not_ compel initialization, it is undeciable for a compiler to catch all cases of use-before-initialize. Some trivial cases can be caught; others can be warned as "_might_ be used before initialization". Consider a trivial case: X: Integer; Y: Character; begin get(Y); if Y = 'a' then X := -3274; else code not involving X end if; put(X); What should the compiler do here? _Maybe_ X will be used before initialization. We cannot know with confidence whether it _will_ be. Does Java _compel_ initialization? Which languages do, in your experience? Mike Feldman ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-21 0:00 ` Michael Feldman @ 1996-07-21 0:00 ` Robert Dewar 1996-07-22 0:00 ` Fergus Henderson 1 sibling, 0 replies; 91+ messages in thread From: Robert Dewar @ 1996-07-21 0:00 UTC (permalink / raw) Mike said "That is a different issue. If Ada _compelled_ initialization, it would be trivial to determine whether all variables were initialized. Certainly the compiler could "enforce" initialization; if you failed to supply an initializer, the compiler would supply a default. There have been earlier threads on why Ada does not compel initialization." No, that's not quite right, there are other ways for the value of a variable to become abnormal, and therefore not guaranteed to be set to a known value. OK, this is not quite the same as never having been initialized, but from a practical point of view, it is the same from the programmer's point of view, namely you have a variable which you better not reference, and it is undecidable whether a given reference runs into trouble with such an abnormal value. Some ways in which values can become abnormal are through the occurrence of an exception during an assignment, through asynchrnonous interruption of a task (via abort or ATC), or via a bad unchecked conversion. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-21 0:00 ` Michael Feldman 1996-07-21 0:00 ` Robert Dewar @ 1996-07-22 0:00 ` Fergus Henderson 1996-07-23 0:00 ` Michael Feldman 1 sibling, 1 reply; 91+ messages in thread From: Fergus Henderson @ 1996-07-22 0:00 UTC (permalink / raw) mfeldman@seas.gwu.edu (Michael Feldman) writes: >Fergus Henderson <fjh@mundook.cs.mu.OZ.AU> wrote: >>mfeldman@seas.gwu.edu (Michael Feldman) writes: >> >>>It _cannot_ be a compiler error, because in general it is undecidable >>>whether a variable is used before it is initialized. >> >>Sure it could be a compiler error. > >[...] you quoted me out of context; we >were talking about Ada, in which there is no _required_ initialization >of variables. In that context, my statement is correct. [...] >The thread was about Ada as it is, not as we might like it to be. Threads do have a habit of shifting topics. When you started talking about what "cannot be", and referred to undecidability to justify your point, rather than referring to the RM, it seemed to me that you were talking about what is or is not logically possible, rather than what happens to be the case. I seem to have misinterpreted you, so my apologies. >Consider a trivial case: > > X: Integer; > Y: Character; > >begin > > get(Y); > if Y = 'a' then > X := -3274; > else > code not involving X > end if; > put(X); > >What should the compiler do here? _Maybe_ X will be used before >initialization. We cannot know with confidence whether it _will_ be. If you're talking about Ada-as-it-is, then the compiler should issue a warning, but accept the code. It should do the same thing even for a code fragment such as X: Integer; begin put(X); unless it can prove that this code fragment will be executed. If you're talking about Ada-as-it-should-be, then the question is more debatable. I think it is a good idea for compilers to warn about such constructs, and a good idea for programmers to always restructure their code to avoid such warnings. If you accept that, it's only a short step from there to agreeing that these messages should be errors rather than warnings. If you transliterate that example from Ada to Mercury, and try compiling the resuling code, the Mercury compiler will report an error "mode mismatch in if-then-else", and will tell you that `X' is bound in one branch of the if-then-else, but not in the other. >Does Java _compel_ initialization? My copy of the Java language specification is elsewhere at the moment, and I don't have a Java compiler at hand to test, so there is a quite large chance that I may be wrong about this, but I _think_ that Java does not require initialization at the point of declaration, but instead requires that a variable be initialized along all the execution paths leading to a possible use of a that variable; that would mean that if a variable wasn't used, there would be no requirement to initialize it. -- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit" PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-22 0:00 ` Fergus Henderson @ 1996-07-23 0:00 ` Michael Feldman 1996-07-23 0:00 ` Robert Dewar ` (2 more replies) 0 siblings, 3 replies; 91+ messages in thread From: Michael Feldman @ 1996-07-23 0:00 UTC (permalink / raw) In article <4svba5$j2i@mulga.cs.mu.OZ.AU>, Fergus Henderson <fjh@mundook.cs.mu.OZ.AU> wrote: >Threads do have a habit of shifting topics. When you started talking >about what "cannot be", and referred to undecidability to justify your >point, rather than referring to the RM, it seemed to me that you were >talking about what is or is not logically possible, rather than what >happens to be the case. I seem to have misinterpreted you, so my >apologies. OK. I think the essence of the discussion is that in a language (like Ada) that does not compel initialization, it is undecidable whether a given variable has a well-defined (put there by the program) value when it is used. > >If you're talking about Ada-as-it-is, then the compiler should issue a >warning, but accept the code. It should do the same thing even for >a code fragment such as > > X: Integer; > begin > put(X); > >unless it can prove that this code fragment will be executed. Indeed. A compiler should give a warning, and in my experience, does, if it can make a reasonably good guess. Some compilers (I think) provide a compile-time flag that the programmer wants to treat warnings as though they were fatal errors. I don;t see anything in gnatinfo to suggest that GNAT does this, though. > >If you're talking about Ada-as-it-should-be, then the question is >more debatable. I think it is a good idea for compilers to warn >about such constructs, and a good idea for programmers to always >restructure their code to avoid such warnings. If you accept that, >it's only a short step from there to agreeing that these messages >should be errors rather than warnings. "Error" vs. "warning" is a bit arbitrary; I think it's really kind of religious. We're talking Ada-as-it-should-be here. For example, a friendly Ada-as-it-is compiler will give a warning if, say, it _knows_ that Constraint_Error will be raised. This cannot legally be an error, and in fact, there are cases where the programmer _wants_ to force an exception in an obvious way (say, to test his exception-handling code!). So the programmer really should have the choice of handling here. The treat-warnings-as-fatal flag would do this. Sure, we could take a religious position that the _default_ should be a fatal error; that would not bother me at all. > >If you transliterate that example from Ada to Mercury, and try >compiling the resuling code, the Mercury compiler will report an error >"mode mismatch in if-then-else", and will tell you that `X' is bound in >one branch of the if-then-else, but not in the other. So Mercury is producing an error where Ada would produce a warning. As I said, I think this is just a matter of taste. > >>Does Java _compel_ initialization? > >My copy of the Java language specification is elsewhere at the moment, >and I don't have a Java compiler at hand to test, so there is a quite >large chance that I may be wrong about this, but I _think_ that >Java does not require initialization at the point of declaration, >but instead requires that a variable be initialized along all the >execution paths leading to a possible use of a that variable; >that would mean that if a variable wasn't used, there would be >no requirement to initialize it. And if it _was_ used? How does the JBC interpreter know whether it's been initialized? Possibly in the interpreter, there's a "this space is uninitialized" flag. As I recall, there have even been such bits in certain hardware architectures. But the "undecidability" issue was referring to the _general_ platform case for Ada-as-it-is. Mike Feldman ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` Michael Feldman @ 1996-07-23 0:00 ` Robert Dewar 1996-07-25 0:00 ` Fergus Henderson 1996-07-24 0:00 ` Robert A Duff 1996-07-24 0:00 ` Fergus Henderson 2 siblings, 1 reply; 91+ messages in thread From: Robert Dewar @ 1996-07-23 0:00 UTC (permalink / raw) Mike said "Indeed. A compiler should give a warning, and in my experience, does, if it can make a reasonably good guess. Some compilers (I think) provide a compile-time flag that the programmer wants to treat warnings as though they were fatal errors. I don;t see anything in gnatinfo to suggest that GNAT does this, though." Mike, remember that GNAT is part of gcc, *all* the usual gcc options apply, as documented in the gcc manual. The following is from gnatinfo.txt: In the usual procedures for using GNAT, Ada source programs are compiled into object files using the driver program 'gcc' with the option '-c' (compile only). Gcc recognizes the ada filename extensions .ads and .adb (discussed more thoroughly below) and calls the actual compiler, 'gnat1' to compile the source file. Gcc has many switches explained in your gcc documentation. In addition, gcc passes certain switches to gnat1. These (with a couple of exceptional abbreviations) are spelled on the gcc command line by "-gnatXXX". In "your gcc documentation" you will find the switch -Wuninitialized, which, used together with -O, causes gcc to give warnings for uninitialized variables. The GNAT frontend also catches some cases itself. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` Robert Dewar @ 1996-07-25 0:00 ` Fergus Henderson 0 siblings, 0 replies; 91+ messages in thread From: Fergus Henderson @ 1996-07-25 0:00 UTC (permalink / raw) dewar@cs.nyu.edu (Robert Dewar) writes: >Mike said > > "Indeed. A compiler should give a warning, and in my experience, does, > if it can make a reasonably good guess. Some compilers (I think) > provide a compile-time flag that the programmer wants to treat warnings > as though they were fatal errors. I don;t see anything in gnatinfo to > suggest that GNAT does this, though." > >Mike, remember that GNAT is part of gcc, *all* the usual gcc options apply, >as documented in the gcc manual. [...] >In "your gcc documentation" you will find the switch -Wuninitialized, which, >used together with -O, causes gcc to give warnings for uninitialized >variables. The GNAT frontend also catches some cases itself. I think Mike was looking for gcc's `-Werror' option, which makes it treat warnings as errors. -- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit" PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` Michael Feldman 1996-07-23 0:00 ` Robert Dewar @ 1996-07-24 0:00 ` Robert A Duff 1996-07-25 0:00 ` Richard A. O'Keefe 1996-07-24 0:00 ` Fergus Henderson 2 siblings, 1 reply; 91+ messages in thread From: Robert A Duff @ 1996-07-24 0:00 UTC (permalink / raw) There's a lot of stuff about warnings in this thread. With regard to uninit vars, the compiler can categorize each variable reference as one of (1) correct, (2) wrong, or (3) don't know. A goal, of course, is to make the compiler as smart as possible, so the likelihood of category (3) is as small as possible. The halting theorem tells we can't shrink (3) to zero (given the rules of Ada). Clearly, the compiler should warn for (2), not warn for (1). But what should it do for (3)? False warnings can be such a big pain as to make all the warnings useless. I don't want to clutter my code with useless initializations, in cases where I'm smart enough to prove it, but the compiler isn't. My experience is that most compilers leave a *lot* of cases in category (3). Opinions? - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-24 0:00 ` Robert A Duff @ 1996-07-25 0:00 ` Richard A. O'Keefe 0 siblings, 0 replies; 91+ messages in thread From: Richard A. O'Keefe @ 1996-07-25 0:00 UTC (permalink / raw) bobduff@world.std.com (Robert A Duff) writes: >With regard to uninit vars, the compiler can categorize each variable >reference as one of (1) correct, (2) wrong, or (3) don't know. >Clearly, the compiler should warn for (2), not warn for (1). But what >should it do for (3)? Leave it to the programmer. Let it be Options|Compiler|PossibleUninit|On or whatever. At least make it _available_. For what it's worth, whenever Lint has given me a bogus warning, the code in question has been so warped that it has warranted a rewrite anyway. The same goes double with lclint. If you really truly believe that programs should be written to be maintainable, then the slogan "not no obvious errors, but obviously no errors" means that it shouldn't be hard for a programmer or a compiler to see that the code is right. That means treating "I can't tell whether this is initialised or not" messages as warnings that the code is hard to understand. Both lint and lclint offer the choice of - globally suppressing such messages from the command line - locally annotating a fragment of code to say that a certain warning should be suppressed (in fact, lclint will, if asked, warning if the expected number of warnings _isn't_ suppressed, so that suppressions obsoleted by code changes don't go unnoticed). The latter leaves a visible warning to maintainers in the source code: "something funny is going on here, but trust me". -- Fifty years of programming language research, and we end up with C++ ??? Richard A. O'Keefe; http://www.cs.rmit.edu.au/~ok; RMIT Comp.Sci. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` Michael Feldman 1996-07-23 0:00 ` Robert Dewar 1996-07-24 0:00 ` Robert A Duff @ 1996-07-24 0:00 ` Fergus Henderson 2 siblings, 0 replies; 91+ messages in thread From: Fergus Henderson @ 1996-07-24 0:00 UTC (permalink / raw) mfeldman@seas.gwu.edu (Michael Feldman) writes: >I think the essence of the discussion is that in a language >(like Ada) that does not compel initialization, it is undecidable >whether a given variable has a well-defined (put there by the program) >value when it is used. Yes, but remember that if you're willing to accept approximate solutions, you can solve undecidable problems. >>[...] I _think_ that >>Java does not require initialization at the point of declaration, >>but instead requires that a variable be initialized along all the >>execution paths leading to a possible use of a that variable; >>that would mean that if a variable wasn't used, there would be >>no requirement to initialize it. > >And if it _was_ used? How does the JBC interpreter know whether it's >been initialized? Possibly in the interpreter, there's a "this space >is uninitialized" flag. I believe that it is done by static checking, not by run-time checking. (I think the static checking is done twice, once by the Java compiler, and then again by the byte-code verifier in the JBC interpreter when it first loads the JBC code.) I don't know how Java handles arrays. But I'm sure there are lots of Java experts in comp.lang.java.* that would be happy to answer such questions. -- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit" PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-19 0:00 ` Dale Stanbrough 1996-07-19 0:00 ` James A. Squire @ 1996-07-19 0:00 ` Adam Beneschan 1 sibling, 0 replies; 91+ messages in thread From: Adam Beneschan @ 1996-07-19 0:00 UTC (permalink / raw) Dale Stanbrough <dale@goanna.cs.rmit.edu.au> writes: >Adam Beneschan writes: >"Well, you can't read an "out" parameter at all, so it's illegal to use > "op" in the right-hand side of your assignment. So the compiler > should give you an error. Also, in Ada83, you'll get an error because > I needs to be declared before the code for SubP appears. > > If you change op to an "in out" parameter, you'll be reading an > uninitialized variable, but typically neither the compiler nor the > runtime will complain." > > >Ada95 does allow you to read out parameters. The code written simply >uses an uninitialized variable, and I would imagine it would be declared >erroneous by the LRM. Sorry, I wasn't aware of this change. This rule change frightens me a little. In the posted example: procedure SubP (op : out integer) is begin op := op + 1; end SubP; I've been known to accidentally type "out" when I mean "in out". In Ada 83, the compiler would catch me, but now it won't, and the effect will be very different because here the "op" on the right side of the assignment is always uninitialized. However, I guess a smart compiler would let me know that I'm using an uninitialized parameter, and perhaps the advantages of letting you read an OUT parameter after you've written to it outweigh this disadvantage. -- Adam ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-18 0:00 ` Adam Beneschan 1996-07-18 0:00 ` Robert Dewar 1996-07-19 0:00 ` Dale Stanbrough @ 1996-07-19 0:00 ` Samuel Tardieu 1996-07-19 0:00 ` John Herro 1996-07-19 0:00 ` Pascal Obry 3 siblings, 1 reply; 91+ messages in thread From: Samuel Tardieu @ 1996-07-19 0:00 UTC (permalink / raw) To: Peter Hermann Pascal> In Ada you can read out parameter, and this program is then Pascal> not valid. It's behavior is unknown. Peter> even more frightening Tuck? I don't see what's frightening here. As I understand it, this point has been introduced to allow things like this: procedure Fact (N : in Positive; R : out Positive) is begin R := 1; for I in 2 .. N loop R := R * I; -- Note that the R out parameter gets read here end loop; end Fact; If you forget to initialize R, then it's your fault and the compiler may warn you as it may do for other uninitialized variables... Sam -- "La cervelle des petits enfants, ca doit avoir comme un petit gout de noisette" Charles Baudelaire ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-19 0:00 ` Samuel Tardieu @ 1996-07-19 0:00 ` John Herro 1996-07-19 0:00 ` Tucker Taft 0 siblings, 1 reply; 91+ messages in thread From: John Herro @ 1996-07-19 0:00 UTC (permalink / raw) Samuel Tardieu <sam@inf.enst.fr> writes that Ada 95 allows reading of "out" parameters to allow things like: > procedure Fact (N : in Positive; R : out Positive) is > begin > R := 1; > for I in 2 .. N loop > R := R * I; -- Note that the R out parameter gets read here > end loop; > end Fact; Yes, but this saves us only one variable declaration and one line in the executable region over the way it would be done in Ada 83: procedure Fact (N : in Positive; R : out Positive) is S : Positive; -- new begin S := 1; for I in 2 .. N loop S := S * I; end loop; R := S; -- new end Fact; - John Herro Software Innovations Technology http://members.aol.com/AdaTutor ftp://members.aol.com/AdaTutor ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-19 0:00 ` John Herro @ 1996-07-19 0:00 ` Tucker Taft 1996-07-23 0:00 ` Peter Hermann 0 siblings, 1 reply; 91+ messages in thread From: Tucker Taft @ 1996-07-19 0:00 UTC (permalink / raw) John Herro (johnherro@aol.com) wrote: : Samuel Tardieu <sam@inf.enst.fr> writes that Ada 95 : allows reading of "out" parameters to allow things like: : > procedure Fact (N : in Positive; R : out Positive) is : > begin : > R := 1; : > for I in 2 .. N loop : > R := R * I; -- Note that the R out parameter gets read : here : > end loop; : > end Fact; : Yes, but this saves us only one variable declaration and one line in : the executable region over the way it would be done in Ada 83: : procedure Fact (N : in Positive; R : out Positive) is : S : Positive; -- new : begin : S := 1; : for I in 2 .. N loop : S := S * I; : end loop; : R := S; -- new : end Fact; It is hard to know which error is more common, the Ada 83 one where you create a local read/write variable and then forget to assign it on all exit paths to the OUT parameter, or the Ada 95 one where you forget to initialize the read/write OUT parameter. Having experienced the Ada 83 situation for 10 years, I remember having made the Ada 83 error several times. It is too early to tell how it will compare in frequency to the Ada 95 error. The main advantage is that it simplifies the language, since you only have one rule -- initialize your variables -- rather than two. Ada 83's unreadable OUT parameters require a special paradigm, and introduce a second class of errors, when you need to build up an answer incrementally. : - John Herro : Software Innovations Technology : http://members.aol.com/AdaTutor : ftp://members.aol.com/AdaTutor -Tucker Taft stt@inmet.com http://www.inmet.com/~stt/ Intermetrics, Inc. Cambridge, MA USA ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-19 0:00 ` Tucker Taft @ 1996-07-23 0:00 ` Peter Hermann 1996-07-23 0:00 ` Robert A Duff 0 siblings, 1 reply; 91+ messages in thread From: Peter Hermann @ 1996-07-23 0:00 UTC (permalink / raw) Tucker Taft (stt@henning.camb.inmet.com) wrote: : It is hard to know which error is more common, the Ada 83 : one where you create a local read/write variable and then forget to : assign it on all exit paths to the OUT parameter, or the Ada 95 : one where you forget to initialize the read/write OUT parameter. : Having experienced the Ada 83 situation for 10 years, I remember : having made the Ada 83 error several times. It is too early to tell me too ... and then quickly changing to John Herro's solution. (while grumbling ;-) : how it will compare in frequency to the Ada 95 error. : The main advantage is that it simplifies the language, since : you only have one rule -- initialize your variables -- rather than : two. Ada 83's unreadable OUT parameters require a special : paradigm, and introduce a second class of errors, when you need : to build up an answer incrementally. For the Ada83 class of errors I ask you for an example. I consider the current Ada95 rule a true source of errors and therefore a nasty property of the language. I could imagine an Ada2005 where the compiler is obliged to only allow any downstream reading of mode-"OUT"-parameters when the context clearly indicates a prior setting, whatever flow of control was taken before. BTW, under NO circumstances I would accept an incoming value of a formal OUT parameter as data to be processed. I am sure you all agree. I am not satisfied with the language concerning the handling of non-initialized variables in general. This has been discussed long time ago. I remember e.g. the efficiency aspect. -- Peter Hermann Tel:+49-711-685-3611 Fax:3758 ph@csv.ica.uni-stuttgart.de Pfaffenwaldring 27, 70569 Stuttgart Uni Computeranwendungen Team Ada: "C'mon people let the world begin" (Paul McCartney) ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` Peter Hermann @ 1996-07-23 0:00 ` Robert A Duff 0 siblings, 0 replies; 91+ messages in thread From: Robert A Duff @ 1996-07-23 0:00 UTC (permalink / raw) In article <4t20tb$1bum@info4.rus.uni-stuttgart.de>, Peter Hermann <ica2ph@alpha1.csv.ica.uni-stuttgart.de> wrote: >For the Ada83 class of errors I ask you for an example. I gave such an example in a previous post. You have to build up the result in a local variable, and the possible bug is that you forget to assign the local into the 'out' parameter. This is at least as likely as the potential bug prevented in Ada 83, which is where you read the 'out' param before initializing it. >I consider the current Ada95 rule a true source of errors >and therefore a nasty property of the language. As explained above, the Ada 83 rule is *also* a true source of errors. The only real solution is to have a comprehensive rule for detecting uninitialized vars, either at run time or compile time (or both). >I could imagine an Ada2005 where the compiler is obliged to only >allow any downstream reading of mode-"OUT"-parameters >when the context clearly indicates a prior setting, >whatever flow of control was taken before. The problem isn't OUT params in particular. The problem is uninit vars. If Ada 05 is to solve the problem, it ought to do so in a uniform manner for all variables, not just OUT parameters. >BTW, under NO circumstances I would accept an incoming value of >a formal OUT parameter as data to be processed. I am sure you all agree. Well, I'll bet you accept incoming discriminants and array bounds. Other than those, I agree. >I am not satisfied with the language concerning >the handling of non-initialized variables in general. Agreed. >This has been discussed long time ago. >I remember e.g. the efficiency aspect. And agreed. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-18 0:00 ` Adam Beneschan ` (2 preceding siblings ...) 1996-07-19 0:00 ` Samuel Tardieu @ 1996-07-19 0:00 ` Pascal Obry 1996-07-19 0:00 ` Peter Hermann 3 siblings, 1 reply; 91+ messages in thread From: Pascal Obry @ 1996-07-19 0:00 UTC (permalink / raw) [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain, Size: 1803 bytes --] adam@irvine.com (Adam Beneschan) wrote: >Paul Whittington <paul@sage.inel.gov> writes: > >In the following Ada program, should either the compiler or the run-time > >get some kind of error because the out parameter is not initialized? > > > >procedure Testit is > > > > procedure SubP (op : out Integer) is > > begin > > op := op+1; > > end SubP; > > > > I : Integer; > > > >begin > > SubP (I); > >end Testit; >Well, you can't read an "out" parameter at all, so it's illegal to use >"op" in the right-hand side of your assignment. So the compiler >should give you an error. Also, in Ada83, you'll get an error because >I needs to be declared before the code for SubP appears. This is wrong for Ada(95). In Ada you can read out parameter, and this program is then not valid. It's behavior is unknown. >If you change op to an "in out" parameter, you'll be reading an >uninitialized variable, but typically neither the compiler nor the >runtime will complain. > -- Adam Pascal. --|------------------------------------------------------------ --| Pascal Obry Team-Ada Member | --| | --| EDF-DER-IPN-SID- Ing�nierie des Syst�mes d'Informations | --| | --| Bureau G1-010 e-mail: pascal.obry@der.edfgdf.fr | --| 1 Av G�n�ral de Gaulle voice : +33-1-47.65.50.91 | --| 92141 Clamart CEDEX fax : +33-1-47.65.50.07 | --| FRANCE | --|------------------------------------------------------------ --| --| http://ourworld.compuserve.com/homepages/pascal_obry --| --| "The best way to travel is by means of imagination" ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-19 0:00 ` Pascal Obry @ 1996-07-19 0:00 ` Peter Hermann 0 siblings, 0 replies; 91+ messages in thread From: Peter Hermann @ 1996-07-19 0:00 UTC (permalink / raw) Pascal Obry (pascal.obry@der.edfgdf.fr) wrote: : > > procedure SubP (op : out Integer) is : > > begin : > > op := op+1; : In Ada you can read out parameter, and this program is then not valid. : It's behavior is unknown. even more frightening Tuck? -- Peter Hermann Tel:+49-711-685-3611 Fax:3758 ph@csv.ica.uni-stuttgart.de Pfaffenwaldring 27, 70569 Stuttgart Uni Computeranwendungen Team Ada: "C'mon people let the world begin" (Paul McCartney) ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-18 0:00 Uninitialized "out" parameters Paul Whittington 1996-07-18 0:00 ` Adam Beneschan @ 1996-07-18 0:00 ` Robert Dewar 1996-07-19 0:00 ` Peter Amey 1996-07-20 0:00 ` Fergus Henderson 1996-07-19 0:00 ` Peter Amey ` (3 subsequent siblings) 5 siblings, 2 replies; 91+ messages in thread From: Robert Dewar @ 1996-07-18 0:00 UTC (permalink / raw) Paul asked "In the following Ada program, should either the compiler or the run-time get some kind of error because the out parameter is not initialized? procedure Testit is procedure SubP (op : out Integer) is begin op := op+1; end SubP; I : Integer; begin SubP (I); end Testit; The answer is that this program is perfectly legal, so it would be incorrect for a compiler to reject it. At execution time, if subp is called, then the addition operation references an uninitialized variable and renders the program execution erroneous, which means anything might happen, but you certainly cannot expect/require a runtime error. The execution might raise Program_Error, but it also might do anything else. A compiler could give a warning for this program. For example, GNAT, using the option -Wuninitialized (warn on uninitialized variable use), gives testit.adb: In function `subp': testit.adb:3: warning: `op' might be used uninitialized in this function But certainly it is impossible for a compiler to give warnings in all cases of uninitialized variable use. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-18 0:00 ` Robert Dewar @ 1996-07-19 0:00 ` Peter Amey 1996-07-20 0:00 ` Fergus Henderson 1 sibling, 0 replies; 91+ messages in thread From: Peter Amey @ 1996-07-19 0:00 UTC (permalink / raw) On 18 Jul 1996, Robert Dewar wrote: [snip] > > But certainly it is impossible for a compiler to give warnings in all > cases of uninitialized variable use. > True, but high-integrity tools like the SPARK Examiner can and do; they also turn out to be a rich source of errors in real programs. Peter ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-18 0:00 ` Robert Dewar 1996-07-19 0:00 ` Peter Amey @ 1996-07-20 0:00 ` Fergus Henderson 1996-07-20 0:00 ` Robert Dewar 1 sibling, 1 reply; 91+ messages in thread From: Fergus Henderson @ 1996-07-20 0:00 UTC (permalink / raw) dewar@cs.nyu.edu (Robert Dewar) writes: >But certainly it is impossible for a compiler to give warnings in all >cases of uninitialized variable use. No, certainly it is possible. There are languages in which any code that might attempt to use an uninitialized variable is a compile-time error. It would certainly be possible for an Ada compiler to give warnings in all cases where a variable might be used before it was initialized. -- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit" PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-20 0:00 ` Fergus Henderson @ 1996-07-20 0:00 ` Robert Dewar 1996-07-21 0:00 ` Fergus Henderson 0 siblings, 1 reply; 91+ messages in thread From: Robert Dewar @ 1996-07-20 0:00 UTC (permalink / raw) Fergus said "No, certainly it is possible. There are languages in which any code that might attempt to use an uninitialized variable is a compile-time error. It would certainly be possible for an Ada compiler to give warnings in all cases where a variable might be used before it was initialized." Well it depends what you mean. If we read what you say literally, it is obviously incorrect, since it requires the halting problem to be solved: procedure x is m,n : integer; begin (big chunk of code not referencing m,n) m := n; end; this code references the uninitialized variable n if and only if the big chunk of code halts. That's an easy proof. If you don't mind getting bogus warnings, i.e. warnings that might be false, then your statement is trivially true, just post a warning on every use (of course your compiler might be more clever than this, but this is again a simple proof. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-20 0:00 ` Robert Dewar @ 1996-07-21 0:00 ` Fergus Henderson 1996-07-21 0:00 ` Robert Dewar 0 siblings, 1 reply; 91+ messages in thread From: Fergus Henderson @ 1996-07-21 0:00 UTC (permalink / raw) dewar@cs.nyu.edu (Robert Dewar) writes: >Fergus said > >"No, certainly it is possible. There are languages in which any code >that might attempt to use an uninitialized variable is a compile-time >error. It would certainly be possible for an Ada compiler to give >warnings in all cases where a variable might be used before it was >initialized." > >Well it depends what you mean. If we read what you say literally, it is >obviously incorrect, since it requires the halting problem to be solved: No, if you read it literally, it's correct -- but you're not reading it literally, you're reading into it more than what I wrote. >If you don't mind getting bogus warnings, i.e. warnings that might be >false, then your statement is trivially true, Yes. I never said anything about not getting some spurious warnings (or spurious errors). Presuming the spurious warnings/errors don't occur often, and so long as there are easy work-arounds when they do occur, I don't think that would be a major problem. Certainly programmers have demonstrated a willingness to accept that sort of thing in other aspect of programming languages (e.g. type systems). > procedure x is > m,n : integer; > begin > (big chunk of code not referencing m,n) > m := n; > end; > >this code references the uninitialized variable n if and only if the big >chunk of code halts. That's an easy proof. Similarly, in a dynamically typed Ada-like language, the code procedure x is m : integer; n : some_other_type; begin (big chunk of code) m := n; end; causes a run-time type error if and only if the big chunk of code halts. Of course, Ada uses static type checking, rather than dynamic typing; they report some "spurious" type errors such as for the example above. There's no reason why Ada compilers couldn't do the analagous sort of thing for uninitialized variables. -- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit" PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-21 0:00 ` Fergus Henderson @ 1996-07-21 0:00 ` Robert Dewar 1996-07-23 0:00 ` Fergus Henderson 1996-07-23 0:00 ` Richard A. O'Keefe 0 siblings, 2 replies; 91+ messages in thread From: Robert Dewar @ 1996-07-21 0:00 UTC (permalink / raw) Fergus said "Similarly, in a dynamically typed Ada-like language, the code procedure x is m : integer; n : some_other_type; begin (big chunk of code) m := n; end; causes a run-time type error if and only if the big chunk of code halts. Of course, Ada uses static type checking, rather than dynamic typing; they report some "spurious" type errors such as for the example above. There's no reason why Ada compilers couldn't do the analagous sort of thing for uninitialized variables." Yes, but Ada is not dyunamically typed, it uses a decidable static type system, and there are VERY good reasons why comparable static systems cannot be designed for dealing with the uninitialized variable problem (please reread carefully my example of the 2 gig array in an allocate on demand environment -- and response to how your decidable system would accomodate this requirement). \x1adp ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-21 0:00 ` Robert Dewar @ 1996-07-23 0:00 ` Fergus Henderson 1996-07-23 0:00 ` Robert A Duff 1996-07-23 0:00 ` Richard A. O'Keefe 1 sibling, 1 reply; 91+ messages in thread From: Fergus Henderson @ 1996-07-23 0:00 UTC (permalink / raw) dewar@cs.nyu.edu (Robert Dewar) writes: >... there are VERY good reasons why comparable static systems >cannot be designed for dealing with the uninitialized variable problem >(please reread carefully my example of the 2 gig array in an allocate >on demand environment -- and response to how your decidable system >would accomodate this requirement). I haven't seen your example. I tried searching for it using dejanews, but I did not find any article in this thread posted by you that gave an example of a 2 gig array. But, even without seeing your example, I'm pretty confident that a statically decidable system could handle those sorts of thing. In fact, for any given set of examples, there is _guaranteed_ to be _some_ statically decidable system which handles those examples! Whether such a system could also be useful, orthogonal, practical, etc. is of course another question; we'd have to see the examples in question to be able to judge. -- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit" PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` Fergus Henderson @ 1996-07-23 0:00 ` Robert A Duff 1996-07-24 0:00 ` Fergus Henderson 1996-07-24 0:00 ` Fergus Henderson 0 siblings, 2 replies; 91+ messages in thread From: Robert A Duff @ 1996-07-23 0:00 UTC (permalink / raw) In article <4t2gb4$a10@mulga.cs.mu.OZ.AU>, Fergus Henderson <fjh@mundook.cs.mu.OZ.AU> wrote: >I haven't seen your example. I tried searching for it using dejanews, >but I did not find any article in this thread posted by you that >gave an example of a 2 gig array. I haven't seen it, either, but I can guess what Robert meant. You declare an array (1..One_Zillion), and you trust the operating system to *not* create storage for most of that array. Normally, you just set the first few elements, and the others are memory-mapped to non-existent storage. If you were required to say ":= (others => something);", then the compiler might actually cause writes to all that memory, causing the OS to actually allocate it, causing Storage_Error, or perhaps just a huge waste of memory. On the other hand, if "something" happens to be, say, "0", then some operating systems can deal with it by initializing memory pages to zero as they are needed. The compiler has to know about that fact, and act accordingly. The DEC Ada-83 compiler on VAX/VMS does this. >But, even without seeing your example, I'm pretty confident that a >statically decidable system could handle those sorts of thing. In general? I skept. >In fact, for any given set of examples, there is _guaranteed_ to be >_some_ statically decidable system which handles those examples! True, but the compiler has to know about those examples, or at least that sort of example. >Whether such a system could also be useful, orthogonal, practical, etc. >is of course another question; we'd have to see the examples in >question to be able to judge. I still prefer run-time checks in this case. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` Robert A Duff @ 1996-07-24 0:00 ` Fergus Henderson 1996-07-24 0:00 ` Fergus Henderson 1 sibling, 0 replies; 91+ messages in thread From: Fergus Henderson @ 1996-07-24 0:00 UTC (permalink / raw) bobduff@world.std.com (Robert A Duff) writes: >Fergus Henderson <fjh@mundook.cs.mu.OZ.AU> wrote: >>But, even without seeing your example, I'm pretty confident that a >>statically decidable system could handle those sorts of thing. > >In general? I skept. Well, the justification is the following theorem, which you agree with: >>In fact, for any given set of examples, there is _guaranteed_ to be >>_some_ statically decidable system which handles those examples! > >True, but the compiler has to know about those examples, or at least >that sort of example. Right. I didn't say that such a system would necessary be useful: >>Whether such a system could also be useful, orthogonal, practical, etc. >>is of course another question; we'd have to see the examples in >>question to be able to judge. So what I'm saying is that it is possible in principle. I think it remains to be seen whether it would be of net benefit in practice. But I think it's certainly something worth exploring. >I still prefer run-time checks in this case. For scalars, static checks should work fine. (One potential difficulty is that for global variables you would need to do global analysis; that would make implementation more difficult in a standard separate compilation environment, but shouldn't pose any fundamental problems. I suppose tasking might also complicate things; I haven't thought about how tasking would interact with this sort of static checking.) Static checks should probably also work fine for records. (Some sort of extended mode system would help for record parameters, so that one could specify that this field has mode `in', and that field has mode `out', rather than having to give a single mode to the whole record.) For arrays, it should be possible to statically verify common patterns of array initialization. For complicated patterns of array initialization, it would be possible to use run-time checks, but run-time checks don't seem to have much advantage over simply requiring the user to pre-initialize the whole array. -- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit" PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` Robert A Duff 1996-07-24 0:00 ` Fergus Henderson @ 1996-07-24 0:00 ` Fergus Henderson 1 sibling, 0 replies; 91+ messages in thread From: Fergus Henderson @ 1996-07-24 0:00 UTC (permalink / raw) bobduff@world.std.com (Robert A Duff) writes: >Fergus Henderson <fjh@mundook.cs.mu.OZ.AU> wrote: >>I haven't seen your example. I tried searching for it using dejanews, >>but I did not find any article in this thread posted by you that >>gave an example of a 2 gig array. > >I haven't seen it, either, but I can guess what Robert meant. You >declare an array (1..One_Zillion), and you trust the operating system to >*not* create storage for most of that array. Normally, you just set the >first few elements, and the others are memory-mapped to non-existent >storage. If you were required to say ":= (others => something);", I would hope that a good static checking system would not require initialization at the point of declaration as the only method of initializing arrays; I would hope that it would allow common patterns of initialization such as initializing all the elements one by one in a loop. >the compiler might actually cause writes to all that memory, causing the >OS to actually allocate it, causing Storage_Error, or perhaps just a >huge waste of memory. I suppose that could be a serious problem (even if it only occurred for uncommon patterns of initialization). But you give a solution: >On the other hand, if "something" happens to be, say, "0", then some >operating systems can deal with it by initializing memory pages to zero >as they are needed. The compiler has to know about that fact, and act >accordingly. The DEC Ada-83 compiler on VAX/VMS does this. -- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit" PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-21 0:00 ` Robert Dewar 1996-07-23 0:00 ` Fergus Henderson @ 1996-07-23 0:00 ` Richard A. O'Keefe 1996-07-23 0:00 ` Robert Dewar 1996-07-23 0:00 ` Robert A Duff 1 sibling, 2 replies; 91+ messages in thread From: Richard A. O'Keefe @ 1996-07-23 0:00 UTC (permalink / raw) dewar@cs.nyu.edu (Robert Dewar) writes: >Yes, but Ada is not dyunamically typed, it uses a decidable static type >system, and there are VERY good reasons why comparable static systems >cannot be designed for dealing with the uninitialized variable problem >(please reread carefully my example of the 2 gig array in an allocate >on demand environment -- and response to how your decidable system >would accomodate this requirement). In my experience of marking student C programs, trying to use uninitialised variables is the commonest non-syntactic error. I have found the program 'lclint' _extremely_ useful when marking because it does a very good job of noticing possible uninitialised variables. It even manages on occasion to do a useful (not perfect) job with arrays. On one student program it reported 62 such warnings, and I thought it was crying wolf, but on closer inspection every single warning (most of the involving arrays) was right. I note that SPARCompiler Pascal, which I do not otherwise care for, has a "-Rw" command line option for extending uninitialised variable tracking into records (but not arrays). Over the last year I have been coming to the conclusion that the ability to use uninitialised variables is one of those programming language features that I am better off without. I mean, ever since "A Discipline of Programming" I thought it was a good idea, but I also thought I was a hot enough programmer not to need such a crutch. Then I started using lclint, and it started finding mistakes that I hadn't noticed. True, Ada is so designed that sound and complete compile-time detection of using uninitialised variables is impossible ('separate' probably contributes something to this). It's also worth noting that the change to 'out' parameters in Ada 95 doesn't make it noticably harder for a compiler that *tries* to do a *useful* amount of checking, as for example gcc -O2 -Wall does. But some day Ada will have a successor. And I can see no reason why that successor should not do a better job than Ada in this respect. I mentioned lclint. lclint does something rather interesting: it tracks the allocation state of pointers, via annotations. In effect, it uses a richer type language than C, in which it is possible to express things like "this is a non-null pointer to an object having no other pointers"; just as Dijkstra's notation tracks "obligation to initialise" in the type system, so lclint tracks "obligation to free" in the type system. Fergus Henderson has posted in this thread. He's involved in the Mercury project, and Mercury, in addition to "types" uses something called "modes" which in effect enrich the type system so that the programmer can say "this procedure takes a record in which the x and y fields are initialised and the z and w fields aren't, and initialises the w field" and the compiler can *prove* at compile time that no uninitialised variable access is possible. There has been other work done on including state and effects in type systems, but lclint and Mercury are practical tools you can FTP today. In the short term, the array problem can be handled the way Dijkstra's notation does: by having dynamic bounds, so that the initialised part of an array is the part within the dynamic bounds, and the rest of the array acts as if it didn't exist. SPARCompiler Pascal has varying [n] of char as its type for strings; this is the same idea as Dijkstra's arrays except that the lower bound is frozen at 1. Such a string may have *room* for 100000 characters, but if it was last assigned a string of 5 characters, those 5 are the only ones you can access. What does that mean for Ada? It means that the use of abstract container types like queues and APL/Fortran-90/Torrix-style "whole array" operations are not just a clearer way to say what you mean, they are a good way to avoid a class of errors. -- Fifty years of programming language research, and we end up with C++ ??? Richard A. O'Keefe; http://www.cs.rmit.edu.au/~ok; RMIT Comp.Sci. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` Richard A. O'Keefe @ 1996-07-23 0:00 ` Robert Dewar 1996-07-24 0:00 ` Robert A Duff ` (3 more replies) 1996-07-23 0:00 ` Robert A Duff 1 sibling, 4 replies; 91+ messages in thread From: Robert Dewar @ 1996-07-23 0:00 UTC (permalink / raw) Richard said True, Ada is so designed that sound and complete compile-time detection of using uninitialised variables is impossible. But some day Ada will have a successor. And I can see no reason why that successor should not do a better job than Ada in this respect. I doubt it, you certainly do not suggest what that better job might be. The rest of your note talks about checking that is not and cannot be completely statically reliable. As for practical tools, any good Ada compiler should indeed warn of many common cases, and tools analogous to lclint are perfectly possible with Ada, and/or should be built into the Ada compiler. Dynamic bounds of arrays do not help in compile time legality checking, so I don't see what relevance they have. And yes, container types are certainly appropriate (after all see Bounded_String, which is exactly what you are talking about), but again, this has nothing to do with compile time legality requirements. Let's try to focus a specific example, the one I gave before, and you tell me how your improved approach will work at compile time to detect as illegalities all references to uninitialized elements. I have an array of 2 gigabytes in an allocate-on-demand environment. I use this as a sparse hash table, but it is critical that only pages that are actually used get referenced, so it is out of the question to initialize the table. How do I make sure that references to this array correspond to previously set elements? Even doing this at runtime is awkward, but I see no way of designing a type system or any other semantic framework to solve this at compile time as a legality issue. It is not good enough to just say "we should do better", you have to say *exactly* how you can do better, or your position is unconvincing. After all, this is an old problem that has not been solved for 38 years now (I am counting from Algol-58, it is a bit longer if you count from the first Fortran), so if you have a solution, it would be nice to present it! ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` Robert Dewar @ 1996-07-24 0:00 ` Robert A Duff 1996-07-24 0:00 ` Fergus Henderson ` (2 subsequent siblings) 3 siblings, 0 replies; 91+ messages in thread From: Robert A Duff @ 1996-07-24 0:00 UTC (permalink / raw) In article <dewar.838132465@schonberg>, Robert Dewar <dewar@cs.nyu.edu> wrote: >I have an array of 2 gigabytes in an allocate-on-demand environment. I use >this as a sparse hash table, but it is critical that only pages that are >actually used get referenced, so it is out of the question to initialize >the table. I don't understand your example. A hash table normally has an operation for determining whether a given item is in the table, and this operation is going to have to read pages that have never been written. So, the allocate-on-demand feature needs to zero out pages upon allocation, or somehow set them to a well-defined value. If I write: Table: Giant_Array := (others => null); I believe the DEC Ada compiler on VAX/VMS will notice that null is zero, and not actually zero out the whole array, but rely on the fact that the operating system will zero out each page as it is allocated. Is this not true? Are there any other Ada compilers smart enough to do this (presuming the underlying OS supports allocate-on-demand)? (Actually, if it's an array of pointers, it will be initialized to null without the aggregate -- we had a big argument here a while back about that.) By the way, a few months ago I wrote a program, and it was running too slow, so I profiled it, and found that it was spending a huge percentage of its time setting access values to their default null value, in cases where I could prove this to be unnecessary. I actually resorted to a pretty ugly hack to get the compiler to quit generating those initializations. I was using GNAT on Linux. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` Robert Dewar 1996-07-24 0:00 ` Robert A Duff @ 1996-07-24 0:00 ` Fergus Henderson 1996-07-24 0:00 ` Fergus Henderson 1996-07-25 0:00 ` Richard A. O'Keefe 3 siblings, 0 replies; 91+ messages in thread From: Fergus Henderson @ 1996-07-24 0:00 UTC (permalink / raw) dewar@cs.nyu.edu (Robert Dewar) writes: >Richard said > > True, Ada is so designed that sound and complete compile-time detection > of using uninitialised variables is impossible. > > But some day Ada will have a successor. And I can see no reason why that > successor should not do a better job than Ada in this respect. > >I doubt it, you certainly do not suggest what that better job might be. The >rest of your note talks about checking that is not and cannot be completely >statically reliable. I disagree. You keep saying that static checking cannot be completely reliable, but this is wrong -- you _can_ get reliable static checking. The down side is that in order to get it, you might have to accept some loss of expressiveness -- but you _can_ get it. For example, the language Sisal has a lot of support for arrays, but I'm pretty sure that in Sisal it's not possible to reference an uninitialized variable at run-time. Now there are probably some things you can do in Ada that you can't do in Sisal, but the restrictions enforced by the Sisal compiler are completely statically reliable. >Let's try to focus a specific example, the one I gave before, and you tell >me how your improved approach will work at compile time to detect as >illegalities all references to uninitialized elements. > >I have an array of 2 gigabytes in an allocate-on-demand environment. I use >this as a sparse hash table, but it is critical that only pages that are >actually used get referenced, so it is out of the question to initialize >the table. I don't understand how your sparse hash table works. Supposing you go to insert a new entry in the hash table, how do you detect a hash collision? Don't you have to initialize at least one field of the hash slots in order to tell whether each hash slot is occupied or not? How do you, as a programmer, know that your code will never reference any uninitialized slots of this hash table? If you can tell me that, then I might be able to figure out a reasonable way for you to tell the compiler the same information. -- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit" PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` Robert Dewar 1996-07-24 0:00 ` Robert A Duff 1996-07-24 0:00 ` Fergus Henderson @ 1996-07-24 0:00 ` Fergus Henderson 1996-07-25 0:00 ` Richard A. O'Keefe 3 siblings, 0 replies; 91+ messages in thread From: Fergus Henderson @ 1996-07-24 0:00 UTC (permalink / raw) dewar@cs.nyu.edu (Robert Dewar) writes: >Dynamic bounds of arrays do not help in compile time legality checking, so >I don't see what relevance they have. And yes, container types are certainly >appropriate (after all see Bounded_String, which is exactly what you are >talking about), but again, this has nothing to do with compile time legality >requirements. I think it does have relevant to the compile time legality requirements. Many container types have an interface that has no possibility of accessing uninitialized variables even if their implementation might make use of uninitialized arrays used in ways that might make it difficult for a static checking system to ensure their safety. For example, if the standard library has a `sparse_hash_table' type, it should solve the problem you mentioned with the 2 gig array. The down side of strict static checking is that it might make some idioms, such as an efficient implementation of the `sparse_hash_table' interface, difficult to express. The relevance of using containers with higher levels of abstraction than arrays is that it allows you to combine efficient implementations with strict static checking while minimizing any loss of expressiveness. -- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit" PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` Robert Dewar ` (2 preceding siblings ...) 1996-07-24 0:00 ` Fergus Henderson @ 1996-07-25 0:00 ` Richard A. O'Keefe 1996-07-25 0:00 ` Robert A Duff 3 siblings, 1 reply; 91+ messages in thread From: Richard A. O'Keefe @ 1996-07-25 0:00 UTC (permalink / raw) dewar@cs.nyu.edu (Robert Dewar) writes: >Richard said > True, Ada is so designed that sound and complete compile-time detection > of using uninitialised variables is impossible. > But some day Ada will have a successor. And I can see no reason why that > successor should not do a better job than Ada in this respect. >I doubt it, you certainly do not suggest what that better job might be. I certainly *thought* I did. Reference to Mercury isn't a suggestion? Reference to Dijkstra's notation isn't a suggestion? Gosh, I'm on the wrong planet again. From a requirements point of view, a better job is this: the *combination* of the run time checks and the static mode/type checks is such that any attempt to use an uninitialised variable will certainly be reported unless the programmer chose to suppress such checks. >The >rest of your note talks about checking that is not and cannot be completely >statically reliable. This is the same kind of hard-to-swallow straw man argument that Tom Lord is using in the GC list to argue "because it isn't perfect, you shouldn't say it's desirable." As long as the compile time checks can be suppressed, I don't *care* about the occasional false alarm. In the case of Mercury, the mode (instantiation state) system occasionally rules out at compile time programs that would have a reasonable interpretation, but this is no different from a type system, which also rules out at compile time programs that would have a reasonable interpretation. If memory serves me correctly, there was an Algol 60 compiler (I have the source, published by the CWI, but it's in Auckland) which allowed 'procedure' foo(N, A); 'value' N; 'integer' A; 'array' A; 'begin' 'if' N = 1 'then' A[1] := 0.0 'else' A[1,2] := 0.0; 'end'; with the type check done dynamically. In Ada, this is no longer allowed, and you don't say "the Ada type check cannot be completely statically reliable", you say "programs that don't make it through the Ada type system are *usually* wrong, so we think it's a good tradeoff that some programs are rejected even though no "type" error would have occurred at run time." >As for practical tools, any good Ada compiler should >indeed warn of many common cases, and tools analogous to lclint are >perfectly possible with Ada, and/or should be built into the Ada compiler. Here, if nowhere else, we are very much in agreement. So let me show you an example of the kind of thing that gcc warns about for C, that the Ada compiler available to our students does not warn about. Script started on Thu 25 Jul 1996 06:12:11 PM EST g% cat undef.adb with Ada.Text_IO, Ada.Integer_Text_IO; procedure Undef is X, Y: Integer; begin Ada.Integer_Text_IO.Get(Y); if Y = 0 then X := 1; end if; Ada.Integer_Text_IO.Put(X); Ada.Text_IO.New_Line; end Undef; g% rm undef undef.ali undef.o g% gnatmake undef gcc -c undef.adb gnatbind -x undef.ali gnatlink undef.ali g% ./undef 1 0 g% rm undef undef.ali undef.o g% gnatmake undef -cargs -O2 -Wall gcc -c -O2 -Wall undef.adb gnatbind -x undef.ali gnatlink undef.ali g% ./undef 1 1 g% script done on Thu 25 Jul 1996 06:14:14 PM EST Never mind arrays, it is possible to do a much better job than this for scalars. I have read gnatinfo.txt version 1.98, and the pattern /un(-|)init/ does not occur in it, so if there is some option I should be setting to get a warning for this, I think it is pardonable that I have not found it. >Dynamic bounds of arrays do not help in compile time legality checking, so >I don't see what relevance they have. This is a lot like saying "the run time range checks in Ada do not help in compile time legality checking, so I don't see what relevance they have". In both cases, whether it is state or type we are talking about, the compiler checks what it can, and there is something left over to be checked at run time. Dynamic bounds help the compiler because they give it less work to do. They completely solve the 2Gb array example (which I haven't seen yet either, but I'm guessing) because all the compiler has to prove is that the array elements are accessed *through* the array, not by any other means which might bypass checking. >Let's try to focus a specific example, the one I gave before, and you tell >me how your improved approach will work at compile time to detect as >illegalities all references to uninitialized elements. >I have an array of 2 gigabytes in an allocate-on-demand environment. I use >this as a sparse hash table, but it is critical that only pages that are >actually used get referenced, so it is out of the question to initialize >the table. >How do I make sure that references to this array correspond to previously >set elements? Even doing this at runtime is awkward, but I see no way of >designing a type system or any other semantic framework to solve this at >compile time as a legality issue. Gosh, how this reminds me of the "Ada doesn't have bitwise operations, so we ought to do everything in C" arguments. I don't have a solution if you insist that the thing be modelled by a simple array. That's not a failure on my part, because I'm arguing that simple C-style arrays are a problem. Since we are talking about a very large structure, the structure is not a simple "uniform cost" structure anyway. What's really going on underneath is in some sense an array of pointers (the page table), and it's not going to cost us a lot to use a multilevel structure ourselves. Each page of that multilevel structure can be fully initialised when it is created. I have often done this. >It is not good enough to just say "we should do better", you have to say >*exactly* how you can do better, or your position is unconvincing. After >all, this is an old problem that has not been solved for 38 years now >(I am counting from Algol-58, it is a bit longer if you count from the >first Fortran), so if you have a solution, it would be nice to present it! There are a lot of old solutions, too. If you insist "but you MUST be able to handle arrays exactly the way they are now or I'll say Nyah-nyah", then you'll be saying nyah'nyah until the last proton decays. -- Fifty years of programming language research, and we end up with C++ ??? Richard A. O'Keefe; http://www.cs.rmit.edu.au/~ok; RMIT Comp.Sci. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-25 0:00 ` Richard A. O'Keefe @ 1996-07-25 0:00 ` Robert A Duff 0 siblings, 0 replies; 91+ messages in thread From: Robert A Duff @ 1996-07-25 0:00 UTC (permalink / raw) In article <4t7amf$701@goanna.cs.rmit.edu.au>, Richard A. O'Keefe <ok@goanna.cs.rmit.edu.au> wrote: > 'procedure' foo(N, A); > 'value' N; 'integer' A; > 'array' A; > 'begin' > 'if' N = 1 'then' A[1] := 0.0 'else' A[1,2] := 0.0; > 'end'; >with the type check done dynamically. In Ada, this is no longer allowed, >and you don't say "the Ada type check cannot be completely statically >reliable", you say "programs that don't make it through the Ada type >system are *usually* wrong, so we think it's a good tradeoff that some >programs are rejected even though no "type" error would have occurred >at run time." Well, that's true to a great extent, but the Ada 83 designers also said "for cases where flexibility is more important, we'll give them variant records", and the Ada 95 designers said, "for those cases, we'll give them class-wide types". Both features (variant records and class-wide types) involve some amount of run-time checking. In fact one major advantage of class-wide types is that more cases can be checked at compile time, but it's never a case of "everything is checked at compile time, and all run-time checks are evil". >...In both cases, whether it is state or type we are talking about, >the compiler checks what it can, and there is something left over to be >checked at run time. From that statement, it sound to me like everybody's in agreement. >There are a lot of old solutions, too. If you insist "but you MUST be >able to handle arrays exactly the way they are now or I'll say Nyah-nyah", >then you'll be saying nyah'nyah until the last proton decays. True. We're talking about language design in an Ada newsgroup, and some people are thinking "what (if anything) would be reasonable to add to Ada without changing the entire type model and everything else", and others are thinking "what is a good way to do this, assuming we are allowed to design the entire language from scratch". These are two different questions! (I enjoy thinking about both.) - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` Richard A. O'Keefe 1996-07-23 0:00 ` Robert Dewar @ 1996-07-23 0:00 ` Robert A Duff 1996-07-24 0:00 ` Richard A. O'Keefe 1 sibling, 1 reply; 91+ messages in thread From: Robert A Duff @ 1996-07-23 0:00 UTC (permalink / raw) In article <4t1s3n$chv@goanna.cs.rmit.edu.au>, Richard A. O'Keefe <ok@goanna.cs.rmit.edu.au> wrote: >In my experience of marking student C programs, trying to use uninitialised >variables is the commonest non-syntactic error. This doesn't necessarily indicate a need for compile-time checks. It indicates a need for something -- possibly compile-time, possibly run-time, possibly some mixture. And you get the usual trade-offs among efficiency, early error detection, and flexibility. >... I have found the program >'lclint' _extremely_ useful when marking because it does a very good job of >noticing possible uninitialised variables. So why don't your students use lclint? - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` Robert A Duff @ 1996-07-24 0:00 ` Richard A. O'Keefe 1996-07-24 0:00 ` Robert A Duff ` (2 more replies) 0 siblings, 3 replies; 91+ messages in thread From: Richard A. O'Keefe @ 1996-07-24 0:00 UTC (permalink / raw) bobduff@world.std.com (Robert A Duff) writes: >In article <4t1s3n$chv@goanna.cs.rmit.edu.au>, >Richard A. O'Keefe <ok@goanna.cs.rmit.edu.au> wrote: >>In my experience of marking student C programs, trying to use uninitialised >>variables is the commonest non-syntactic error. >This doesn't necessarily indicate a need for compile-time checks. It >indicates a need for something -- possibly compile-time, possibly >run-time, possibly some mixture. And you get the usual trade-offs among >efficiency, early error detection, and flexibility. Bob Duff is the last person I would have expected to argue against static checks. Roughly the third most frightening thing I have seen in a computer manual is the advice "If your program is halting with range-checking errors, and you don't want to address those problems immediately, you can always omit the {$R+} compiler directive [thus suppressing the range checks] for the time being." to be found in the Turbo Pascal 5.0 User Guide on p207. If I can get a compile-time error (when it is provable that an uninitialised variable will be used) or warning (when it is not provable that it won't), why *not*? In computing, ignorance is bliss. Run-time checks only tell you whether the path followed *this time* through the code encountered an uninitialised variable or not. One of the things we are trying hard to teach is "just because your program didn't crash on YOUR test cases doesn't mean it won't crash on OURS", and relying too much on run-time checks would tend to exacerbate the problem. As things stand, I *do* have ready access to tools that do *some* static uninitialised variable checking for C: lint, gcc -O2 -Wall, and lclint. I would of course like to have ready access, at a price suitable for a not-very-rich university whose government is talking about 10% cuts to education funding, to run-time checks for C, and to similar compile time and run time checks for Ada. >>... I have found the program >>'lclint' _extremely_ useful when marking because it does a very good job of >>noticing possible uninitialised variables. >So why don't your students use lclint? To be really honest, because I didn't tell them about it. I *love* lclint, but it is a free system with a one-mand-and-his-dog maintenance team, and it tends to have trouble with system headers (sometimes because they are extremely non-standard C, sometimes because they are standard but c****y C, sometimes because lclint needs improving) and it produces a *LOT* of messages. I have the background and patience to work through long lists of messages and to work around the occasional failure of the tool, the students don't. On the other hand, they *are* told about lint, and they still don't use that. Heck, in the last assignment, a couple of students handed in C++ and I don't mean just C-with-//-comments (nor do I mean that it took *advantage* of C++, just happened to be different enough not to be even close to compiling under C). If it comes to that, they are also told to compile with gcc, and I even gave them a shell script to use that set -O2 -Wall, and they didn't do that either. What this leads up to is that a compiler for *student* use needs to have a high level of static checking switched *by default*. -- Fifty years of programming language research, and we end up with C++ ??? Richard A. O'Keefe; http://www.cs.rmit.edu.au/~ok; RMIT Comp.Sci. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-24 0:00 ` Richard A. O'Keefe @ 1996-07-24 0:00 ` Robert A Duff 1996-07-25 0:00 ` Richard A. O'Keefe 1996-07-24 0:00 ` Theodore E. Dennison 1996-07-25 0:00 ` Frank Manning 2 siblings, 1 reply; 91+ messages in thread From: Robert A Duff @ 1996-07-24 0:00 UTC (permalink / raw) In article <4t4r0s$8te@goanna.cs.rmit.edu.au>, Richard A. O'Keefe <ok@goanna.cs.rmit.edu.au> wrote: >Bob Duff is the last person I would have expected to argue against static >checks. I'm not sure why it surprises you -- after all, I had a hand in writing an RM that has more run-time checks than you can shake a stick at. ;-) Anyway, the decision between compile-time and run-time checking is always a trade off between safety and flexibility (among other things). Whenever you check something at compile time, the check is necessarily stricter than it needs to be -- the halting theorem tells us that. Consider the case of divide-by-zero. We could easily catch all divides-by-zero at compile time, if we're willing to be overly conservative. However, this would make the language a lot less useful. >... Roughly the third most frightening thing I have seen in a computer >manual is the advice > "If your program is halting with range-checking errors, > and you don't want to address those problems immediately, > you can always omit the {$R+} compiler directive > [thus suppressing the range checks] for the time being." >to be found in the Turbo Pascal 5.0 User Guide on p207. Wow. That is indeed amazingly bad advice. >If I can get a compile-time error (when it is provable that an uninitialised >variable will be used) or warning (when it is not provable that it won't), >why *not*? ... I certainly agree with the first part (just like I want the compiler to complain if it *knows* I'm going to divide by zero). But the second part is questionable. It means I'm going to get a lot of spurious warnings, since my programs typically contain lots of pointers to heap-allocated records, and it's not feasible for a compiler to do a very good job for that kind of data. So what do I do with all those warnings? Well, I can ignore them, but that's horrible, because every time I recompile something, I will keep getting the same stupid warnings -- the compiler is to stupid to realize that I've already analyzed those particular warnings, and satisfied myself that they're bogus. So if there's ever a *correct* warning, I'll probably miss it. So, instead, what I have to do is add in some junk code that makes the compiler shut up. For example, I'd probably have to default-initialize every record component, whether it needs it or not. Note that in this case, run-time checks will probably find more bugs than compile-time checks. This is because I added in all those bogus initializations to some nonsense value. So if I do have a bug, I'll get that nonsense value, and perhaps get a wrong answer. (At least it will be the *same* wrong answer every time!) Whereas if the checking were done at run time, I would get an exception. (And of course I understand that I might fail to test that execution path, which is the problem with run-time checking.) Of course, with most Ada compilers, I don't get run-time checks, and I may or may not get compile-time warnings in some small subset of the cases. Anyway, I don't believe compile time checking is always better than run time checking. It's a trade-off, and the language designer has to consider the details of each case. The compiler writer, too, for deciding what warnings to produce. >What this leads up to is that a compiler for *student* use needs to have >a high level of static checking switched *by default*. Probably a good idea. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-24 0:00 ` Robert A Duff @ 1996-07-25 0:00 ` Richard A. O'Keefe 1996-07-25 0:00 ` Robert A Duff 0 siblings, 1 reply; 91+ messages in thread From: Richard A. O'Keefe @ 1996-07-25 0:00 UTC (permalink / raw) bobduff@world.std.com (Robert A Duff) writes: >Richard A. O'Keefe <ok@goanna.cs.rmit.edu.au> wrote: >>Bob Duff is the last person I would have expected to argue against static >>checks. >I'm not sure why it surprises you -- after all, I had a hand in writing >an RM that has more run-time checks than you can shake a stick at. ;-) Because your postings have given me reason to believe you are a very competent programmer (Robert Dewar's postings have given me the same impression of him, even if we don't see eye-to-eye). >Consider the case of divide-by-zero. We could easily catch all >divides-by-zero at compile time, if we're willing to be overly >conservative. However, this would make the language a lot less useful. You are telling this to a programmer who is in the habit of making sure that every integer division involves a divisor declared to be Positive rather than Integer, and thinks that this is one good reason for using Ada instead of C. Floating point divide by zero, that's another matter. >>If I can get a compile-time error (when it is provable that an uninitialised >>variable will be used) or warning (when it is not provable that it won't), >>why *not*? ... >I certainly agree with the first part (just like I want the compiler to >complain if it *knows* I'm going to divide by zero). But the second >part is questionable. It means I'm going to get a lot of spurious >warnings, since my programs typically contain lots of pointers to >heap-allocated records, and it's not feasible for a compiler to do a >very good job for that kind of data. It _isn't_? But I've seen lclint *DO* it! And so does Mercury. It may or may not be feasible for an Ada95 compiler to do a good job; I have never written an Ada95 compiler and can't presume to judge what is or is not feasible for that. What I *can* say is that it isn't just "feasible" in principle, there are systems that DO it. Of course this means having a richer type system, in which it is possible to express "X is a non-null pointer to a record with an initialised Y field, an initialised Z field, and an uninitialised W field". To a first approximation, the Mercury type/mode system does exactly that. It's even possible for such a type system to keep track of whether pointers are unique or not (Clean does this, it's in the Mercury type system, and the lclint checker does a practically useful job of it for C). I wish people wouldn't keep telling me that it isn't feasible to do what several of the tools I use *DO* do. This is not rocket science! >Note that in this case, run-time checks will probably find more bugs >than compile-time checks. I am not arguing *against* run-time checks. I am arguing against run-time checks as a substitute for compile-time checks. I would be delighted to have both. If I have to put up with only one, I will take the compile time checks; I do not want to impose the run-time burdens that Robert Dewar has listed on other programmers. >Anyway, I don't believe compile time checking is always better than run >time checking. It's a trade-off, and the language designer has to >consider the details of each case. The compiler writer, too, for >deciding what warnings to produce. Compile time checking of property Z, in a language that permits it, - forbids some meaningful programs - ensures that a class of errors is not present - has lower run-time penalties, and because the compiler knows more, may permit the generation of better code Run time checking of property Z, in an implementation that permits it, - places fewer restrictions on source programs - ensures that a class of errors will not be *executed* without warning - has higher run-time penalties. You can substitute the property of your choice for Z. When Z = "type correctness", it's widely used as a stick to beat Lisp with. Existing systems show that the analogy holds for Z = initialised/not and Z = null/non-null unique/shared pointer in languages designed with such checks in mind. How much of this could be carried over to a language like Ada that was *not* designed with such checks in mind is a practical issue on which Robert Dewar and others can speak with authority and I cannot. All I can say is that lclint shows that you can do a lot more than you might think. -- Fifty years of programming language research, and we end up with C++ ??? Richard A. O'Keefe; http://www.cs.rmit.edu.au/~ok; RMIT Comp.Sci. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-25 0:00 ` Richard A. O'Keefe @ 1996-07-25 0:00 ` Robert A Duff 0 siblings, 0 replies; 91+ messages in thread From: Robert A Duff @ 1996-07-25 0:00 UTC (permalink / raw) In article <4t7chp$9mk@goanna.cs.rmit.edu.au>, Richard A. O'Keefe <ok@goanna.cs.rmit.edu.au> wrote: >You are telling this to a programmer who is in the habit of making >sure that every integer division involves a divisor declared to be >Positive rather than Integer, and thinks that this is one good reason >for using Ada instead of C. Yeah, I try to do similar things, when possible. BUT, first of all it doesn't always work. Division is well defined for negatives and positives, but not zero, and Ada has no "non-zero" constraint. Also, you're not detecting divide-by-zero at compile time using this technique. You're detecting it earlier, which is good, but still at run time. "X: Positive := <some-expression>;" is checked at run time. >Compile time checking of property Z, in a language that permits it, > - forbids some meaningful programs > - ensures that a class of errors is not present > - has lower run-time penalties, and because the compiler knows > more, may permit the generation of better code >Run time checking of property Z, in an implementation that permits it, > - places fewer restrictions on source programs > - ensures that a class of errors will not be *executed* without warning > - has higher run-time penalties. Yes, that's what I meant by "it's a trade-off". - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-24 0:00 ` Richard A. O'Keefe 1996-07-24 0:00 ` Robert A Duff @ 1996-07-24 0:00 ` Theodore E. Dennison 1996-07-25 0:00 ` Frank Manning 2 siblings, 0 replies; 91+ messages in thread From: Theodore E. Dennison @ 1996-07-24 0:00 UTC (permalink / raw) Richard A. O'Keefe wrote: > If it comes to that, they are also told to compile with gcc, and I even > gave them a shell script to use that set -O2 -Wall, and they didn't do > that either. > > What this leads up to is that a compiler for *student* use needs to have > a high level of static checking switched *by default*. Why don't you have the default .cshrc (or .login) alias "gcc" to "gcc -O2 -Wall"? -- T.E.D. | Work - mailto:dennison@escmail.orl.mmc.com | | Home - mailto:dennison@iag.net | | URL - http://www.iag.net/~dennison | ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-24 0:00 ` Richard A. O'Keefe 1996-07-24 0:00 ` Robert A Duff 1996-07-24 0:00 ` Theodore E. Dennison @ 1996-07-25 0:00 ` Frank Manning 1996-07-25 0:00 ` Richard A. O'Keefe 2 siblings, 1 reply; 91+ messages in thread From: Frank Manning @ 1996-07-25 0:00 UTC (permalink / raw) In article <4t4r0s$8te@goanna.cs.rmit.edu.au> ok@goanna.cs.rmit.edu.au (Richard A. O'Keefe) writes: > Roughly the third most frightening thing I have seen in a computer > manual is the advice > "If your program is halting with range-checking errors, > and you don't want to address those problems immediately, > you can always omit the {$R+} compiler directive > [thus suppressing the range checks] for the time being." > to be found in the Turbo Pascal 5.0 User Guide on p207. Not to be argumentative, but I'm curious as to why you think this is so bad? Granted, it's bad if a programmer gives in to the temptation to release a program that fails unless range checks are suppressed. On the other hand, it might be useful to examine the behavior of the program if you can somehow prevent it from halting, if only for diagnostic purposes. -- Frank Manning ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-25 0:00 ` Frank Manning @ 1996-07-25 0:00 ` Richard A. O'Keefe 1996-07-26 0:00 ` Frank Manning 0 siblings, 1 reply; 91+ messages in thread From: Richard A. O'Keefe @ 1996-07-25 0:00 UTC (permalink / raw) frank@bigdog.engr.arizona.edu (Frank Manning) writes: :In article <4t4r0s$8te@goanna.cs.rmit.edu.au> ok@goanna.cs.rmit.edu.au :(Richard A. O'Keefe) writes: :> Roughly the third most frightening thing I have seen in a computer :> manual is the advice :> "If your program is halting with range-checking errors, :> and you don't want to address those problems immediately, :> you can always omit the {$R+} compiler directive :> [thus suppressing the range checks] for the time being." :> to be found in the Turbo Pascal 5.0 User Guide on p207. :Not to be argumentative, but I'm curious as to why you think this is so :bad? Because once such a check would have failed, the program is operating in never-never land, and any *other* problems you may chose to address first may, in fact, be artefacts of the nonsense you are guaranteed to be getting. If your program is halting with range-checking errors, the only kind of problem that it is useful to diagnose is a problem that occurs *before* that halt. Which means that you want to switch additional checks on so the program halts *earlier*, if anything. This is especially true in a programming language running on old DOS, where a range check failure that is not caught may mean that your program has just scribbled all over the operating system or the debugger... -- Fifty years of programming language research, and we end up with C++ ??? Richard A. O'Keefe; http://www.cs.rmit.edu.au/~ok; RMIT Comp.Sci. ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-25 0:00 ` Richard A. O'Keefe @ 1996-07-26 0:00 ` Frank Manning 0 siblings, 0 replies; 91+ messages in thread From: Frank Manning @ 1996-07-26 0:00 UTC (permalink / raw) In article <4t7cnd$9t1@goanna.cs.rmit.edu.au> ok@goanna.cs.rmit.edu.au (Richard A. O'Keefe) writes: <Pros/cons of suppressing range checks temporarily> > Because once such a check would have failed, the program is operating > in never-never land, and any *other* problems you may chose to address > first may, in fact, be artefacts of the nonsense you are guaranteed to > be getting. > > If your program is halting with range-checking errors, > the only kind of problem that it is useful to diagnose is a problem > that occurs *before* that halt. Which means that you want to switch > additional checks on so the program halts *earlier*, if anything. OK -- sounds reasonable to me. Thanks for answering my question. One nit -- I'm not sure I'd go so far as to say you're *guaranteed* to get nonsense from the program. Suppose overwritten memory is unused or non-critical? I can't help but wonder how much commercial software is out there that would fail if range-checking was active. (My Pascal is rusty -- I assume the manual's use of "range-checking" refers to array indices going out of bounds?) -- Frank Manning ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-18 0:00 Uninitialized "out" parameters Paul Whittington 1996-07-18 0:00 ` Adam Beneschan 1996-07-18 0:00 ` Robert Dewar @ 1996-07-19 0:00 ` Peter Amey 1996-07-19 0:00 ` Michel Gauthier ` (2 subsequent siblings) 5 siblings, 0 replies; 91+ messages in thread From: Peter Amey @ 1996-07-19 0:00 UTC (permalink / raw) > procedure Testit is > > procedure SubP (op : out Integer) is > begin > op := op+1; > end SubP; > If Ada83, the compiler should object to the referencing of an out parameter. With Ada95 this is allowed but I would expect the expression op := op + 1 to pick up a random value from memory; if this random value + 1 was outside the range for integer then a run-time error should occur. Peter ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-18 0:00 Uninitialized "out" parameters Paul Whittington ` (2 preceding siblings ...) 1996-07-19 0:00 ` Peter Amey @ 1996-07-19 0:00 ` Michel Gauthier 1996-07-21 0:00 ` Robert A Duff 1996-07-21 0:00 ` Robert A Duff 1996-07-23 0:00 ` John Herro 5 siblings, 1 reply; 91+ messages in thread From: Michel Gauthier @ 1996-07-19 0:00 UTC (permalink / raw) In article <31EEACDA.64880EEB@sage.inel.gov>, Paul Whittington <paul@sage.inel.gov> wrote: >> In the following Ada program, should either the compiler or the run-time >> get some kind of error because the out parameter is not initialized? >> procedure Testit is >> procedure SubP (op : out Integer) is >> begin >> op := op+1; >> end SubP; >> I : Integer; >> begin >> SubP (I); >> end Testit; IMHO, Ada83 'out' parameters were cleanly defined, although sometimes unpleasent when the compiler answered 'non-readable', but the Ada95 choice is somewhat ugly (unless am I entirely mistaking), and does not correspond to any intuitive view of 'out'. Here, the intuitive behaviour would be preferably raising Program_error, or any alternate allowed behaviour compatible with the 'non-initialised' 'bounded error'. I guess it is, which I have not checked. This problem is harmless here, but can lead to counterintuitive results when the type implies initialisation (records, controlled types, access types). Intuitively, the actual parameter should be Finalize'd prior to entering the subprogram, and re-Initialize'd as part of elaborating the declarative part of the subprogram ___Is it the behaviour that results from LRM ?___ Apologies in advance if I am mistaking, but I guess it useful to make 'out' clearer than it seems to be. QUESTION : wouldn't it be worth abandoning any use of 'out' parameters ? ---------- ---------- ---------- ---------- Michel Gauthier / Laboratoire d'informatique 123 avenue Albert Thomas / F-87060 Limoges telephone +33 () 55457335 [or ~ 7232] fax +33 () 55457315 [or ~7201] ---------- ---------- ---------- ---------- La grande equation de la fin du siecle : windows-X = Mac-Y The main end-of-century equation : windows-X = Mac-Y ---------- ---------- ---------- ---------- Si l'an 2000 est pour vous un mysticisme stupide, utilisez la base 9 If you feel year 2000 a stupid mystic craze, use numeration base 9 ---------- ---------- ---------- ---------- ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-19 0:00 ` Michel Gauthier @ 1996-07-21 0:00 ` Robert A Duff 0 siblings, 0 replies; 91+ messages in thread From: Robert A Duff @ 1996-07-21 0:00 UTC (permalink / raw) In article <gauthier-1907961215520001@164.81.60.62>, Michel Gauthier <gauthier@unilim.fr> wrote: >This problem is harmless here, but can lead to counterintuitive results when >the type implies initialisation (records, controlled types, access types). >Intuitively, the actual parameter should be Finalize'd prior to entering the >subprogram, and re-Initialize'd as part of elaborating the declarative part >of the subprogram ___Is it the behaviour that results from LRM ?___ No. Controlled types are always passed by reference. That is, the formal is a view of the actual (not a copy of it). So no finalization takes place on parameter passing. The original example used an integer. The parameter passing rules are different, depending on what sort of type you have. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-18 0:00 Uninitialized "out" parameters Paul Whittington ` (3 preceding siblings ...) 1996-07-19 0:00 ` Michel Gauthier @ 1996-07-21 0:00 ` Robert A Duff 1996-07-23 0:00 ` John Herro 5 siblings, 0 replies; 91+ messages in thread From: Robert A Duff @ 1996-07-21 0:00 UTC (permalink / raw) In article <31EEACDA.64880EEB@sage.inel.gov>, Paul Whittington <paul@sage.inel.gov> wrote: >In the following Ada program, should either the compiler or the run-time >get some kind of error because the out parameter is not initialized? > >procedure Testit is > > procedure SubP (op : out Integer) is > begin > op := op+1; > end SubP; > > I : Integer; > >begin > SubP (I); >end Testit; Boy, I saw a lot of misinformation in this thread. The above is legal (meaning OK at compile time), although it was illegal in Ada 83. At run time, it's a reference to an uninitialized variable. In Ada 95, such references are a bounded error. The program might raise Program_Error, or Constraint_Error on the bad reference to op. Or, it might continue executing with some value. This value may cause an exception later on. Details of exactly what can happen are in the RM (and AARM). In any case, it's not erroneous -- saying "A(I) := 3;" cannot trash random memory locations, and saying "case I is ..." cannot cause a wild jump. This is the general rule for uninitialized variables -- not a special rule about 'out' parameters. Note that the above would still be true if I were initialized to some correct value before the call. The call to SubP will de-initialize I (unless the compiler chooses to catch the error at run time). Note that the rules are different for access types, and for composites; there are certain types that cannot get de-initialized. But here, we have an integer. A friendly compiler might catch the error and raise an exception. To increase the probability of that happening, you can say "pragma Initialize_Scalars". A compiler can also give a warning about uninit vars, at compile time. But the problem is, such warnings are necessarily either overkill or underkill. (Overkill = sometimes warn about perfectly correct programs. Underkill = miss some incorrect cases.) Overkill might be acceptable if the compiler were smart enough, but separate compilation gets in the way of doing a really good job. My experience is that if warnings continually "cry wolf", then they're worse than useless. Some people pointed out that the new rule allowing reads of uninitialized variables can cause bugs. True, but the old rule can also cause bugs: procedure Get_Total(A: Some_Array; Total: out Integer) is Result: Integer := 0; begin for I in A'Range loop Result := Result + A(I); end loop; -- Oops, I forgot to say "Total := Result;". end Get_Total; Somebody pointed out that it's possible to define a language such that uninit vars are impossible. Certainly true. I've used languages like that. I found that it worked OK for local variables, but for components of records allocated in the heap, it didn't help -- it just meant that the programmer has to initialize all such components explicitly to a bogus value, which actually hides bugs, rather than preventing them. IMHO, the best solution is to have run-time checks, along with some way to suppress the checks if they turn out to be too inefficient. Pragma Initialize_Scalars *almost* does that, but it doesn't work in all cases. And it requires writing the pragma. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-18 0:00 Uninitialized "out" parameters Paul Whittington ` (4 preceding siblings ...) 1996-07-21 0:00 ` Robert A Duff @ 1996-07-23 0:00 ` John Herro 1996-07-23 0:00 ` Robert Dewar ` (2 more replies) 5 siblings, 3 replies; 91+ messages in thread From: John Herro @ 1996-07-23 0:00 UTC (permalink / raw) bobduff@world.std.com (Robert A Duff) writes: > The problem isn't OUT params in particular. > The problem is uninit vars. If Ada 05 is to > solve the problem, it ought to do so in a > uniform manner for all variables, not just > OUT parameters. I agree! Perhaps Ada 0Y should test for reads of unititialized variables at run time by default; this could be turned off with a pragma. When I was in college in the 60's, I wrote a Fortran IV program that stored into part of an array, and then accidentally read from a part of the array that hadn't been stored into. The run-time system caught it, and I was *delighted*! (I don't think my error could have been detected at compile time.) I think the Fortran compiler must have allocated much additional memory to keep track of which array elements were stored into. It was a very worthwhile expense! If "Ada, oh why?" does the same thing by default, it would use extra memory and CPU time, but improve reliability and increase the chances of detecting errors. This is certainly in keeping with the Ada philosophy. It's analogous to Ada doing bounds checking at run time, which can be turned off with a pragma. - John Herro Software Innovations Technology http://members.aol.com/AdaTutor ftp://members.aol.com/AdaTutor ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` John Herro @ 1996-07-23 0:00 ` Robert Dewar 1996-07-24 0:00 ` Peter Hermann 1996-07-23 0:00 ` Robert A Duff 1996-07-26 0:00 ` Stephen J Bevan 2 siblings, 1 reply; 91+ messages in thread From: Robert Dewar @ 1996-07-23 0:00 UTC (permalink / raw) John Herro said " If "Ada, oh why?" does the same thing by default, it would use extra memory and CPU time, but improve reliability and increase the chances of detecting errors. This is certainly in keeping with the Ada philosophy. It's analogous to Ada doing bounds checking at run time, which can be turned off with a pragma." It is quite unlikely that the parameters that went into the original Ada 83 decision will have changed, they certainly had not changed for Ada 95, and I don't see any likelihood that architectures will develop in a direction that makes this feasible. It is not at all analogous to bounds checking. The point with bounds checking is that the cost of this checking, with good compiler optimization, is quite reasonable (in the 10-20% range at most, for typical programs). The cost of runtime checking of uninitialized variables is MUCH higher. If you have a type which fills the complete hardware type (e.g. Character, or Unsigned_32, or, in any reasonable implementation Integer), then you have to maintain and test a separate boolean bit. Not only does this double the register pressure, but also it generates potential pipeline breaks in many architectures which would be very harmful peformance. Of course there may be specialized architectures which make this kind of testing feasible, and of course you are certainly allowed to implement this in Ada 83 or Ada 95 (raising Program_Error as the result of failing the test), but it is interesting to note that there has been almost no demand for such implementations, since in the real world, the interest in performance and easy interface to the outside world would mean that these checks would almost always have to be suppressed. The challenge of the Ada design is to provide a reasonable selection of default runtime checks that do not seriously impact performance. It is of course possible to check everything at runtime, including for example incorrect use of unchecked_conversion and unchecked_deallocation, but these checks are deemed simply too expensive, given the goal of providing a usable high efficiency language. C and C++ take the position of checking nothing at runtime. Some other languages are completely protected (e.g. SNOBOL-4 or SETL). Ada tries to get most of the advantages of runtime checking without paying too high a price. Checking for uninitialized variables is deemed across the line (note that this decision was not particularly controversial, though it was discussed). One thing that John may not realize is that the intent is that the checks in Ada be inexpensive enough that many or most real applicatoins can afford to leave them on. I certainly understand that beginners may want an Ada system that checks uninitialized variables, and of course Ada/Ed always had this capability, but it does not seem a significant priority in commercial implementations of Ada (by commercial here, I mean usable in real applications). I certainly see nothing in this discussion that has added anything to the understanding of the issue when it was first discussed (with respect to Ada) twenty years ago. If anything the development of RISC architectural techniques has strengthened the argument *against* adding such a requirement, and it did not even come up in the revision (I can't even rememeber it being mentioned in the revision requests, and they sure mentioned lots of stuff!) ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` Robert Dewar @ 1996-07-24 0:00 ` Peter Hermann 0 siblings, 0 replies; 91+ messages in thread From: Peter Hermann @ 1996-07-24 0:00 UTC (permalink / raw) Robert Dewar (dewar@cs.nyu.edu) wrote: : I certainly understand that beginners may want an Ada system that checks : uninitialized variables, and of course Ada/Ed always had this capability, so I am a beginner, by definition :-( -- Peter Hermann Tel:+49-711-685-3611 Fax:3758 ph@csv.ica.uni-stuttgart.de Pfaffenwaldring 27, 70569 Stuttgart Uni Computeranwendungen Team Ada: "C'mon people let the world begin" (Paul McCartney) ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` John Herro 1996-07-23 0:00 ` Robert Dewar @ 1996-07-23 0:00 ` Robert A Duff 1996-07-26 0:00 ` Stephen J Bevan 2 siblings, 0 replies; 91+ messages in thread From: Robert A Duff @ 1996-07-23 0:00 UTC (permalink / raw) In article <4t3f1u$t0u@newsbf02.news.aol.com>, John Herro <johnherro@aol.com> wrote: > I agree! Perhaps Ada 0Y should test for reads of unititialized >variables at run time by default; this could be turned off with a pragma. I agree, too, but I think we can let the market decide, rather than waiting for Ada 0Y. Ada 95 compilers are allowed but not required to do just that. So, if customers really want it, one would hope that the compiler vendors will do it. Please don't remind me of the sad fact that the market doesn't always decide rational things in the computer business... ;-) Also, remember that pragma Initialize_Scalars, or whatever it's called, comes pretty close to this ideal. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-23 0:00 ` John Herro 1996-07-23 0:00 ` Robert Dewar 1996-07-23 0:00 ` Robert A Duff @ 1996-07-26 0:00 ` Stephen J Bevan 1996-07-26 0:00 ` Robert A Duff 2 siblings, 1 reply; 91+ messages in thread From: Stephen J Bevan @ 1996-07-26 0:00 UTC (permalink / raw) In article <dewar.838165848@schonberg> dewar@cs.nyu.edu (Robert Dewar) writes: Of course there may be specialized architectures which make this kind of testing feasible, and of course you are certainly allowed to implement this in Ada 83 or Ada 95 (raising Program_Error as the result of failing the test), but it is interesting to note that there has been almost no demand for such implementations, since in the real world, the interest in performance and easy interface to the outside world would mean that these checks would almost always have to be suppressed. I would have thought that the success of Purify shows that there is a great demand for such tools in the C(++) world. It isn't clear to me why it should be any different for Ada. I for one would be very interested in using an Ada compiler that could *optionally* detect references to uninitialised variables at runtime (and at compile time where possible), until that time I'll carry on using GNAT (can't beat it at the price :-). ^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: Uninitialized "out" parameters 1996-07-26 0:00 ` Stephen J Bevan @ 1996-07-26 0:00 ` Robert A Duff 0 siblings, 0 replies; 91+ messages in thread From: Robert A Duff @ 1996-07-26 0:00 UTC (permalink / raw) In article <STEPHENB.96Jul26101657@sorrol.harlqn.co.uk>, Stephen J Bevan <stephenb@harlequin.co.uk> wrote: >I would have thought that the success of Purify shows that there is a >great demand for such tools in the C(++) world. It isn't clear to me >why it should be any different for Ada. Well, there are *some* differences. Pointers can't be uninitialized in Ada, and uninit pointers are probably the nastiest sort of uninit vars. Also (in Ada 95 only), "A[I] := 7;" cannot overwrite arbitrary storage. If I is uninit, then it will either trash some random element of A, or raise an exception -- it won't trash anything *else*. That said, I agree with you. Purify-like tools are valuable for Ada, too. >... I for one would be very >interested in using an Ada compiler that could *optionally* detect >references to uninitialised variables at runtime (and at compile time >where possible),... I agree. - Bob ^ permalink raw reply [flat|nested] 91+ messages in thread
end of thread, other threads:[~2016-04-08 7:32 UTC | newest] Thread overview: 91+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2016-04-05 12:02 Uninitialized out parameters ahlan 2016-04-05 13:17 ` rieachus 2016-04-05 14:07 ` ahlan 2016-04-06 9:45 ` Mark Lorenzen 2016-04-06 21:01 ` Jeffrey R. Carter 2016-04-07 7:10 ` ahlan 2016-04-05 16:19 ` G.B. 2016-04-06 8:19 ` ahlan 2016-04-06 10:17 ` G.B. 2016-04-06 11:44 ` Dennis Lee Bieber 2016-04-06 20:41 ` Niklas Holsti 2016-04-06 20:54 ` Randy Brukardt 2016-04-06 20:47 ` Randy Brukardt 2016-04-06 21:01 ` Randy Brukardt 2016-04-06 21:22 ` Dmitry A. Kazakov 2016-04-07 7:27 ` Randy Brukardt 2016-04-06 11:37 ` AdaMagica 2016-04-06 13:44 ` ahlan 2016-04-06 14:09 ` Mark Lorenzen 2016-04-06 14:10 ` G.B. 2016-04-06 20:53 ` Stefan.Lucks 2016-04-06 21:03 ` Randy Brukardt 2016-04-06 21:12 ` Niklas Holsti 2016-04-06 21:30 ` Randy Brukardt 2016-04-07 9:56 ` Stefan.Lucks 2016-04-07 16:08 ` AdaMagica 2016-04-07 23:02 ` Randy Brukardt 2016-04-08 7:32 ` Dmitry A. Kazakov 2016-04-07 7:52 ` Georg Bauhaus -- strict thread matches above, loose matches on Subject: below -- 1996-07-29 0:00 W. Wesley Groleau (Wes) 1996-07-18 0:00 Uninitialized "out" parameters Paul Whittington 1996-07-18 0:00 ` Adam Beneschan 1996-07-18 0:00 ` Robert Dewar 1996-07-19 0:00 ` Dale Stanbrough 1996-07-19 0:00 ` James A. Squire 1996-07-19 0:00 ` Adam Beneschan 1996-07-20 0:00 ` Michael Feldman 1996-07-21 0:00 ` Fergus Henderson 1996-07-21 0:00 ` Michael Feldman 1996-07-21 0:00 ` Robert Dewar 1996-07-22 0:00 ` Fergus Henderson 1996-07-23 0:00 ` Michael Feldman 1996-07-23 0:00 ` Robert Dewar 1996-07-25 0:00 ` Fergus Henderson 1996-07-24 0:00 ` Robert A Duff 1996-07-25 0:00 ` Richard A. O'Keefe 1996-07-24 0:00 ` Fergus Henderson 1996-07-19 0:00 ` Adam Beneschan 1996-07-19 0:00 ` Samuel Tardieu 1996-07-19 0:00 ` John Herro 1996-07-19 0:00 ` Tucker Taft 1996-07-23 0:00 ` Peter Hermann 1996-07-23 0:00 ` Robert A Duff 1996-07-19 0:00 ` Pascal Obry 1996-07-19 0:00 ` Peter Hermann 1996-07-18 0:00 ` Robert Dewar 1996-07-19 0:00 ` Peter Amey 1996-07-20 0:00 ` Fergus Henderson 1996-07-20 0:00 ` Robert Dewar 1996-07-21 0:00 ` Fergus Henderson 1996-07-21 0:00 ` Robert Dewar 1996-07-23 0:00 ` Fergus Henderson 1996-07-23 0:00 ` Robert A Duff 1996-07-24 0:00 ` Fergus Henderson 1996-07-24 0:00 ` Fergus Henderson 1996-07-23 0:00 ` Richard A. O'Keefe 1996-07-23 0:00 ` Robert Dewar 1996-07-24 0:00 ` Robert A Duff 1996-07-24 0:00 ` Fergus Henderson 1996-07-24 0:00 ` Fergus Henderson 1996-07-25 0:00 ` Richard A. O'Keefe 1996-07-25 0:00 ` Robert A Duff 1996-07-23 0:00 ` Robert A Duff 1996-07-24 0:00 ` Richard A. O'Keefe 1996-07-24 0:00 ` Robert A Duff 1996-07-25 0:00 ` Richard A. O'Keefe 1996-07-25 0:00 ` Robert A Duff 1996-07-24 0:00 ` Theodore E. Dennison 1996-07-25 0:00 ` Frank Manning 1996-07-25 0:00 ` Richard A. O'Keefe 1996-07-26 0:00 ` Frank Manning 1996-07-19 0:00 ` Peter Amey 1996-07-19 0:00 ` Michel Gauthier 1996-07-21 0:00 ` Robert A Duff 1996-07-21 0:00 ` Robert A Duff 1996-07-23 0:00 ` John Herro 1996-07-23 0:00 ` Robert Dewar 1996-07-24 0:00 ` Peter Hermann 1996-07-23 0:00 ` Robert A Duff 1996-07-26 0:00 ` Stephen J Bevan 1996-07-26 0:00 ` Robert A Duff
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox